{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "BuyM4I2f-FrW"
   },
   "source": [
    "# Split Learning and Label Leakage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "  warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "2023-10-07 20:50:39,437\tINFO worker.py:1538 -- Started a local Ray instance.\n"
     ]
    }
   ],
   "source": [
    "import secretflow as sf\n",
    "import matplotlib.pyplot as plt\n",
    "import os\n",
    "\n",
    "os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"-1\"\n",
    "sf.init([\"client\", \"server\"], address=\"local\")\n",
    "client, server = sf.PYU(\"client\"), sf.PYU(\"server\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "\n",
    "# PROJ_DIR = '/home/kyzhang/myfile/sf/github/ExPloit-main'\n",
    "# sys.path.append(os.path.join(PROJ_DIR))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tensorflow import keras\n",
    "from tensorflow.keras import layers\n",
    "import tensorflow as tf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "id": "c6HcMly6_Yq9"
   },
   "outputs": [],
   "source": [
    "def create_first_net(input_dim, hidden_dim, name=\"first_net\"):\n",
    "    # Create model\n",
    "    def create_model():\n",
    "        from tensorflow import keras\n",
    "        from tensorflow.keras import layers\n",
    "        import tensorflow as tf\n",
    "\n",
    "        model = keras.Sequential(\n",
    "            [\n",
    "                keras.Input(shape=input_dim),\n",
    "                layers.Dense(hidden_dim // 2, activation=\"relu\"),\n",
    "                layers.Dense(hidden_dim, activation=\"relu\"),\n",
    "            ]\n",
    "        )\n",
    "        # Compile model\n",
    "        model.summary()\n",
    "        # learning_rate = 1e-3  # 设置学习率\n",
    "        # optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)\n",
    "        optimizer = tf.keras.optimizers.Adam()\n",
    "        model.compile(\n",
    "            loss=\"binary_crossentropy\",\n",
    "            optimizer=optimizer,\n",
    "            metrics=[\"accuracy\", tf.keras.metrics.AUC()],\n",
    "        )\n",
    "        return model\n",
    "\n",
    "    return create_model\n",
    "\n",
    "\n",
    "def create_zero_net(input_dim, hidden_dim, name=\"zero_net\"):\n",
    "    # Create model\n",
    "    def create_model():\n",
    "        from tensorflow import keras\n",
    "        from tensorflow.keras import layers\n",
    "        import tensorflow as tf\n",
    "\n",
    "        model = keras.Sequential(\n",
    "            [\n",
    "                keras.Input(shape=input_dim),\n",
    "                layers.Dense(hidden_dim, activation=\"relu\"),\n",
    "            ]\n",
    "        )\n",
    "        # Compile model\n",
    "        model.summary()\n",
    "        # learning_rate = 1e-3  # 设置学习率\n",
    "        # optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)\n",
    "        optimizer = tf.keras.optimizers.Adam()\n",
    "        model.compile(\n",
    "            loss=\"binary_crossentropy\",\n",
    "            optimizer=optimizer,\n",
    "            metrics=[\"accuracy\", tf.keras.metrics.AUC()],\n",
    "        )\n",
    "        return model\n",
    "\n",
    "    return create_model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_fuse_model(\n",
    "    input_dim_1, input_dim_2, output_dim, party_nums, name=\"fuse_model\"\n",
    "):\n",
    "    def create_model():\n",
    "        from tensorflow import keras\n",
    "        from tensorflow.keras import layers\n",
    "        import tensorflow as tf\n",
    "\n",
    "        # input\n",
    "        input_layers = []\n",
    "        # for i in range(party_nums):\n",
    "        input_layers.append(\n",
    "            keras.Input(\n",
    "                input_dim_1,\n",
    "            )\n",
    "        )\n",
    "        input_layers.append(\n",
    "            keras.Input(\n",
    "                input_dim_2,\n",
    "            )\n",
    "        )\n",
    "\n",
    "        merged_layer = layers.concatenate(input_layers)\n",
    "        output = layers.Dense(output_dim, activation=\"sigmoid\")(merged_layer)\n",
    "        # output = layers.Dense(output_dim, activation='relu')(fuse_layer)\n",
    "\n",
    "        model = keras.Model(inputs=input_layers, outputs=output)\n",
    "        model.summary()\n",
    "\n",
    "        # learning_rate = 1e-3  # 设置学习率\n",
    "        # optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)\n",
    "        optimizer = tf.keras.optimizers.Adam()\n",
    "\n",
    "        model.compile(\n",
    "            loss=\"binary_crossentropy\",\n",
    "            optimizer=optimizer,\n",
    "            metrics=[\"accuracy\", tf.keras.metrics.AUC()],\n",
    "        )\n",
    "        return model\n",
    "\n",
    "    return create_model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_surrogate_model(\n",
    "    input_dim_1, input_dim_2, output_dim, party_nums, name=\"surrogate_model\"\n",
    "):\n",
    "    def create_model():\n",
    "        from tensorflow import keras\n",
    "        from tensorflow.keras import layers\n",
    "        import tensorflow as tf\n",
    "\n",
    "        model = keras.Sequential(\n",
    "            [\n",
    "                keras.Input(shape=input_dim_1 + input_dim_2),\n",
    "                layers.Dense(64, activation=\"relu\"),\n",
    "                layers.Dense(output_dim, activation=\"sigmoid\"),\n",
    "            ]\n",
    "        )\n",
    "        model.summary()\n",
    "\n",
    "        # learning_rate = 1e-3  # 设置学习率\n",
    "        # optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)\n",
    "        optimizer = tf.keras.optimizers.Adam()\n",
    "\n",
    "        model.compile(\n",
    "            loss=\"binary_crossentropy\",\n",
    "            optimizer=optimizer,\n",
    "            metrics=[\"accuracy\", tf.keras.metrics.AUC()],\n",
    "        )\n",
    "        return model\n",
    "\n",
    "    return create_model"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "l3jrDrel_zsO"
   },
   "source": [
    "## Parameters and Pre-processing"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:50:49,391 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29478117376; capacity: 3936380534784. Object creation will fail if spilling is required.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Examples:\n",
      "    Total: 284807\n",
      "    Positive: 492 (0.17% of total)\n",
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2023-10-07 20:50:49.626342: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "from secretflow.utils.simulation.datasets import dataset\n",
    "\n",
    "raw_df = pd.read_csv(\n",
    "    \"https://storage.googleapis.com/download.tensorflow.org/data/creditcard.csv\"\n",
    ")\n",
    "raw_df_neg = raw_df[raw_df[\"Class\"] == 0]\n",
    "raw_df_pos = raw_df[raw_df[\"Class\"] == 1]\n",
    "\n",
    "down_df_neg = raw_df_neg  # .sample(40000)\n",
    "down_df = pd.concat([down_df_neg, raw_df_pos])\n",
    "\n",
    "neg, pos = np.bincount(down_df[\"Class\"])\n",
    "total = neg + pos\n",
    "print(\n",
    "    \"Examples:\\n    Total: {}\\n    Positive: {} ({:.2f}% of total)\\n\".format(\n",
    "        total, pos, 100 * pos / total\n",
    "    )\n",
    ")\n",
    "\n",
    "p_pos = pos / total\n",
    "p_values = tf.constant([1 - p_pos, p_pos], dtype=tf.float32)\n",
    "H_y = -p_pos * tf.math.log(p_pos) - (1 - p_pos) * tf.math.log(1 - p_pos)\n",
    "y_pri = tf.expand_dims(p_values, axis=0)\n",
    "\n",
    "args_dict = {\n",
    "    \"H_y\": H_y,\n",
    "    \"y_pri\": y_pri,\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "cleaned_df = down_df.copy()\n",
    "# You don't want the `Time` column.\n",
    "cleaned_df.pop(\"Time\")\n",
    "# The `Amount` column covers a huge range. Convert to log-space.\n",
    "eps = 0.001  # 0 => 0.1¢\n",
    "cleaned_df[\"Log Ammount\"] = np.log(cleaned_df.pop(\"Amount\") + eps)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>V5</th>\n",
       "      <th>V6</th>\n",
       "      <th>V7</th>\n",
       "      <th>V8</th>\n",
       "      <th>V9</th>\n",
       "      <th>V10</th>\n",
       "      <th>V11</th>\n",
       "      <th>V12</th>\n",
       "      <th>V13</th>\n",
       "      <th>V14</th>\n",
       "      <th>...</th>\n",
       "      <th>V20</th>\n",
       "      <th>V21</th>\n",
       "      <th>V22</th>\n",
       "      <th>V23</th>\n",
       "      <th>V24</th>\n",
       "      <th>V25</th>\n",
       "      <th>V26</th>\n",
       "      <th>V27</th>\n",
       "      <th>V28</th>\n",
       "      <th>Log Ammount</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>-0.338321</td>\n",
       "      <td>0.462388</td>\n",
       "      <td>0.239599</td>\n",
       "      <td>0.098698</td>\n",
       "      <td>0.363787</td>\n",
       "      <td>0.090794</td>\n",
       "      <td>-0.551600</td>\n",
       "      <td>-0.617801</td>\n",
       "      <td>-0.991390</td>\n",
       "      <td>-0.311169</td>\n",
       "      <td>...</td>\n",
       "      <td>0.251412</td>\n",
       "      <td>-0.018307</td>\n",
       "      <td>0.277838</td>\n",
       "      <td>-0.110474</td>\n",
       "      <td>0.066928</td>\n",
       "      <td>0.128539</td>\n",
       "      <td>-0.189115</td>\n",
       "      <td>0.133558</td>\n",
       "      <td>-0.021053</td>\n",
       "      <td>5.008105</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0.060018</td>\n",
       "      <td>-0.082361</td>\n",
       "      <td>-0.078803</td>\n",
       "      <td>0.085102</td>\n",
       "      <td>-0.255425</td>\n",
       "      <td>-0.166974</td>\n",
       "      <td>1.612727</td>\n",
       "      <td>1.065235</td>\n",
       "      <td>0.489095</td>\n",
       "      <td>-0.143772</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.069083</td>\n",
       "      <td>-0.225775</td>\n",
       "      <td>-0.638672</td>\n",
       "      <td>0.101288</td>\n",
       "      <td>-0.339846</td>\n",
       "      <td>0.167170</td>\n",
       "      <td>0.125895</td>\n",
       "      <td>-0.008983</td>\n",
       "      <td>0.014724</td>\n",
       "      <td>0.989913</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-0.503198</td>\n",
       "      <td>1.800499</td>\n",
       "      <td>0.791461</td>\n",
       "      <td>0.247676</td>\n",
       "      <td>-1.514654</td>\n",
       "      <td>0.207643</td>\n",
       "      <td>0.624501</td>\n",
       "      <td>0.066084</td>\n",
       "      <td>0.717293</td>\n",
       "      <td>-0.165946</td>\n",
       "      <td>...</td>\n",
       "      <td>0.524980</td>\n",
       "      <td>0.247998</td>\n",
       "      <td>0.771679</td>\n",
       "      <td>0.909412</td>\n",
       "      <td>-0.689281</td>\n",
       "      <td>-0.327642</td>\n",
       "      <td>-0.139097</td>\n",
       "      <td>-0.055353</td>\n",
       "      <td>-0.059752</td>\n",
       "      <td>5.936641</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-0.010309</td>\n",
       "      <td>1.247203</td>\n",
       "      <td>0.237609</td>\n",
       "      <td>0.377436</td>\n",
       "      <td>-1.387024</td>\n",
       "      <td>-0.054952</td>\n",
       "      <td>-0.226487</td>\n",
       "      <td>0.178228</td>\n",
       "      <td>0.507757</td>\n",
       "      <td>-0.287924</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.208038</td>\n",
       "      <td>-0.108300</td>\n",
       "      <td>0.005274</td>\n",
       "      <td>-0.190321</td>\n",
       "      <td>-1.175575</td>\n",
       "      <td>0.647376</td>\n",
       "      <td>-0.221929</td>\n",
       "      <td>0.062723</td>\n",
       "      <td>0.061458</td>\n",
       "      <td>4.816249</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-0.407193</td>\n",
       "      <td>0.095921</td>\n",
       "      <td>0.592941</td>\n",
       "      <td>-0.270533</td>\n",
       "      <td>0.817739</td>\n",
       "      <td>0.753074</td>\n",
       "      <td>-0.822843</td>\n",
       "      <td>0.538196</td>\n",
       "      <td>1.345852</td>\n",
       "      <td>-1.119670</td>\n",
       "      <td>...</td>\n",
       "      <td>0.408542</td>\n",
       "      <td>-0.009431</td>\n",
       "      <td>0.798278</td>\n",
       "      <td>-0.137458</td>\n",
       "      <td>0.141267</td>\n",
       "      <td>-0.206010</td>\n",
       "      <td>0.502292</td>\n",
       "      <td>0.219422</td>\n",
       "      <td>0.215153</td>\n",
       "      <td>4.248367</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>279863</th>\n",
       "      <td>-1.566487</td>\n",
       "      <td>-2.010494</td>\n",
       "      <td>-0.882850</td>\n",
       "      <td>0.697211</td>\n",
       "      <td>-2.064945</td>\n",
       "      <td>-5.587794</td>\n",
       "      <td>2.115795</td>\n",
       "      <td>-5.417424</td>\n",
       "      <td>-1.235123</td>\n",
       "      <td>-6.665177</td>\n",
       "      <td>...</td>\n",
       "      <td>1.252967</td>\n",
       "      <td>0.778584</td>\n",
       "      <td>-0.319189</td>\n",
       "      <td>0.639419</td>\n",
       "      <td>-0.294885</td>\n",
       "      <td>0.537503</td>\n",
       "      <td>0.788395</td>\n",
       "      <td>0.292680</td>\n",
       "      <td>0.147968</td>\n",
       "      <td>5.966149</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>280143</th>\n",
       "      <td>0.442581</td>\n",
       "      <td>-1.326536</td>\n",
       "      <td>-1.413170</td>\n",
       "      <td>0.248525</td>\n",
       "      <td>-1.127396</td>\n",
       "      <td>-3.232153</td>\n",
       "      <td>2.858466</td>\n",
       "      <td>-3.096915</td>\n",
       "      <td>-0.792532</td>\n",
       "      <td>-5.210141</td>\n",
       "      <td>...</td>\n",
       "      <td>0.226138</td>\n",
       "      <td>0.370612</td>\n",
       "      <td>0.028234</td>\n",
       "      <td>-0.145640</td>\n",
       "      <td>-0.081049</td>\n",
       "      <td>0.521875</td>\n",
       "      <td>0.739467</td>\n",
       "      <td>0.389152</td>\n",
       "      <td>0.186637</td>\n",
       "      <td>-0.273122</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>280149</th>\n",
       "      <td>-1.120541</td>\n",
       "      <td>-0.003346</td>\n",
       "      <td>-2.234739</td>\n",
       "      <td>1.210158</td>\n",
       "      <td>-0.652250</td>\n",
       "      <td>-3.463891</td>\n",
       "      <td>1.794969</td>\n",
       "      <td>-2.775022</td>\n",
       "      <td>-0.418950</td>\n",
       "      <td>-4.057162</td>\n",
       "      <td>...</td>\n",
       "      <td>0.247968</td>\n",
       "      <td>0.751826</td>\n",
       "      <td>0.834108</td>\n",
       "      <td>0.190944</td>\n",
       "      <td>0.032070</td>\n",
       "      <td>-0.739695</td>\n",
       "      <td>0.471111</td>\n",
       "      <td>0.385107</td>\n",
       "      <td>0.194361</td>\n",
       "      <td>4.355310</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>281144</th>\n",
       "      <td>-0.840618</td>\n",
       "      <td>-2.943548</td>\n",
       "      <td>-2.208002</td>\n",
       "      <td>1.058733</td>\n",
       "      <td>-1.632333</td>\n",
       "      <td>-5.245984</td>\n",
       "      <td>1.933520</td>\n",
       "      <td>-5.030465</td>\n",
       "      <td>-1.127455</td>\n",
       "      <td>-6.416628</td>\n",
       "      <td>...</td>\n",
       "      <td>0.306271</td>\n",
       "      <td>0.583276</td>\n",
       "      <td>-0.269209</td>\n",
       "      <td>-0.456108</td>\n",
       "      <td>-0.183659</td>\n",
       "      <td>-0.328168</td>\n",
       "      <td>0.606116</td>\n",
       "      <td>0.884876</td>\n",
       "      <td>-0.253700</td>\n",
       "      <td>5.501262</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>281674</th>\n",
       "      <td>1.151147</td>\n",
       "      <td>-0.096695</td>\n",
       "      <td>0.223050</td>\n",
       "      <td>-0.068384</td>\n",
       "      <td>0.577829</td>\n",
       "      <td>-0.888722</td>\n",
       "      <td>0.491140</td>\n",
       "      <td>0.728903</td>\n",
       "      <td>0.380428</td>\n",
       "      <td>-1.948883</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.017652</td>\n",
       "      <td>-0.164350</td>\n",
       "      <td>-0.295135</td>\n",
       "      <td>-0.072173</td>\n",
       "      <td>-0.450261</td>\n",
       "      <td>0.313267</td>\n",
       "      <td>-0.289617</td>\n",
       "      <td>0.002988</td>\n",
       "      <td>-0.015309</td>\n",
       "      <td>3.750233</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>284807 rows × 25 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "              V5        V6        V7        V8        V9       V10       V11  \\\n",
       "0      -0.338321  0.462388  0.239599  0.098698  0.363787  0.090794 -0.551600   \n",
       "1       0.060018 -0.082361 -0.078803  0.085102 -0.255425 -0.166974  1.612727   \n",
       "2      -0.503198  1.800499  0.791461  0.247676 -1.514654  0.207643  0.624501   \n",
       "3      -0.010309  1.247203  0.237609  0.377436 -1.387024 -0.054952 -0.226487   \n",
       "4      -0.407193  0.095921  0.592941 -0.270533  0.817739  0.753074 -0.822843   \n",
       "...          ...       ...       ...       ...       ...       ...       ...   \n",
       "279863 -1.566487 -2.010494 -0.882850  0.697211 -2.064945 -5.587794  2.115795   \n",
       "280143  0.442581 -1.326536 -1.413170  0.248525 -1.127396 -3.232153  2.858466   \n",
       "280149 -1.120541 -0.003346 -2.234739  1.210158 -0.652250 -3.463891  1.794969   \n",
       "281144 -0.840618 -2.943548 -2.208002  1.058733 -1.632333 -5.245984  1.933520   \n",
       "281674  1.151147 -0.096695  0.223050 -0.068384  0.577829 -0.888722  0.491140   \n",
       "\n",
       "             V12       V13       V14  ...       V20       V21       V22  \\\n",
       "0      -0.617801 -0.991390 -0.311169  ...  0.251412 -0.018307  0.277838   \n",
       "1       1.065235  0.489095 -0.143772  ... -0.069083 -0.225775 -0.638672   \n",
       "2       0.066084  0.717293 -0.165946  ...  0.524980  0.247998  0.771679   \n",
       "3       0.178228  0.507757 -0.287924  ... -0.208038 -0.108300  0.005274   \n",
       "4       0.538196  1.345852 -1.119670  ...  0.408542 -0.009431  0.798278   \n",
       "...          ...       ...       ...  ...       ...       ...       ...   \n",
       "279863 -5.417424 -1.235123 -6.665177  ...  1.252967  0.778584 -0.319189   \n",
       "280143 -3.096915 -0.792532 -5.210141  ...  0.226138  0.370612  0.028234   \n",
       "280149 -2.775022 -0.418950 -4.057162  ...  0.247968  0.751826  0.834108   \n",
       "281144 -5.030465 -1.127455 -6.416628  ...  0.306271  0.583276 -0.269209   \n",
       "281674  0.728903  0.380428 -1.948883  ... -0.017652 -0.164350 -0.295135   \n",
       "\n",
       "             V23       V24       V25       V26       V27       V28  \\\n",
       "0      -0.110474  0.066928  0.128539 -0.189115  0.133558 -0.021053   \n",
       "1       0.101288 -0.339846  0.167170  0.125895 -0.008983  0.014724   \n",
       "2       0.909412 -0.689281 -0.327642 -0.139097 -0.055353 -0.059752   \n",
       "3      -0.190321 -1.175575  0.647376 -0.221929  0.062723  0.061458   \n",
       "4      -0.137458  0.141267 -0.206010  0.502292  0.219422  0.215153   \n",
       "...          ...       ...       ...       ...       ...       ...   \n",
       "279863  0.639419 -0.294885  0.537503  0.788395  0.292680  0.147968   \n",
       "280143 -0.145640 -0.081049  0.521875  0.739467  0.389152  0.186637   \n",
       "280149  0.190944  0.032070 -0.739695  0.471111  0.385107  0.194361   \n",
       "281144 -0.456108 -0.183659 -0.328168  0.606116  0.884876 -0.253700   \n",
       "281674 -0.072173 -0.450261  0.313267 -0.289617  0.002988 -0.015309   \n",
       "\n",
       "        Log Ammount  \n",
       "0          5.008105  \n",
       "1          0.989913  \n",
       "2          5.936641  \n",
       "3          4.816249  \n",
       "4          4.248367  \n",
       "...             ...  \n",
       "279863     5.966149  \n",
       "280143    -0.273122  \n",
       "280149     4.355310  \n",
       "281144     5.501262  \n",
       "281674     3.750233  \n",
       "\n",
       "[284807 rows x 25 columns]"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "client_data_index = [\n",
    "    col\n",
    "    for col in cleaned_df.columns\n",
    "    if col != \"Class\" and col != \"V1\" and col != \"V2\" and col != \"V3\" and col != \"V4\"\n",
    "]\n",
    "client_data = cleaned_df[client_data_index]\n",
    "client_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>V1</th>\n",
       "      <th>V2</th>\n",
       "      <th>V3</th>\n",
       "      <th>V4</th>\n",
       "      <th>Class</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>-1.359807</td>\n",
       "      <td>-0.072781</td>\n",
       "      <td>2.536347</td>\n",
       "      <td>1.378155</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1.191857</td>\n",
       "      <td>0.266151</td>\n",
       "      <td>0.166480</td>\n",
       "      <td>0.448154</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-1.358354</td>\n",
       "      <td>-1.340163</td>\n",
       "      <td>1.773209</td>\n",
       "      <td>0.379780</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-0.966272</td>\n",
       "      <td>-0.185226</td>\n",
       "      <td>1.792993</td>\n",
       "      <td>-0.863291</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-1.158233</td>\n",
       "      <td>0.877737</td>\n",
       "      <td>1.548718</td>\n",
       "      <td>0.403034</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>279863</th>\n",
       "      <td>-1.927883</td>\n",
       "      <td>1.125653</td>\n",
       "      <td>-4.518331</td>\n",
       "      <td>1.749293</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>280143</th>\n",
       "      <td>1.378559</td>\n",
       "      <td>1.289381</td>\n",
       "      <td>-5.004247</td>\n",
       "      <td>1.411850</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>280149</th>\n",
       "      <td>-0.676143</td>\n",
       "      <td>1.126366</td>\n",
       "      <td>-2.213700</td>\n",
       "      <td>0.468308</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>281144</th>\n",
       "      <td>-3.113832</td>\n",
       "      <td>0.585864</td>\n",
       "      <td>-5.399730</td>\n",
       "      <td>1.817092</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>281674</th>\n",
       "      <td>1.991976</td>\n",
       "      <td>0.158476</td>\n",
       "      <td>-2.583441</td>\n",
       "      <td>0.408670</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>284807 rows × 5 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "              V1        V2        V3        V4  Class\n",
       "0      -1.359807 -0.072781  2.536347  1.378155      0\n",
       "1       1.191857  0.266151  0.166480  0.448154      0\n",
       "2      -1.358354 -1.340163  1.773209  0.379780      0\n",
       "3      -0.966272 -0.185226  1.792993 -0.863291      0\n",
       "4      -1.158233  0.877737  1.548718  0.403034      0\n",
       "...          ...       ...       ...       ...    ...\n",
       "279863 -1.927883  1.125653 -4.518331  1.749293      1\n",
       "280143  1.378559  1.289381 -5.004247  1.411850      1\n",
       "280149 -0.676143  1.126366 -2.213700  0.468308      1\n",
       "281144 -3.113832  0.585864 -5.399730  1.817092      1\n",
       "281674  1.991976  0.158476 -2.583441  0.408670      1\n",
       "\n",
       "[284807 rows x 5 columns]"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "server_data = cleaned_df[[\"V1\", \"V2\", \"V3\", \"V4\", \"Class\"]]\n",
    "server_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>V5</th>\n",
       "      <th>V6</th>\n",
       "      <th>V7</th>\n",
       "      <th>V8</th>\n",
       "      <th>V9</th>\n",
       "      <th>V10</th>\n",
       "      <th>V11</th>\n",
       "      <th>V12</th>\n",
       "      <th>V13</th>\n",
       "      <th>V14</th>\n",
       "      <th>...</th>\n",
       "      <th>V25</th>\n",
       "      <th>V26</th>\n",
       "      <th>V27</th>\n",
       "      <th>V28</th>\n",
       "      <th>Log Ammount</th>\n",
       "      <th>V1</th>\n",
       "      <th>V2</th>\n",
       "      <th>V3</th>\n",
       "      <th>V4</th>\n",
       "      <th>Class</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>649</th>\n",
       "      <td>-0.252045</td>\n",
       "      <td>-0.392240</td>\n",
       "      <td>-0.047177</td>\n",
       "      <td>0.041339</td>\n",
       "      <td>-0.069318</td>\n",
       "      <td>0.169913</td>\n",
       "      <td>0.947708</td>\n",
       "      <td>0.417596</td>\n",
       "      <td>-0.798841</td>\n",
       "      <td>0.679509</td>\n",
       "      <td>...</td>\n",
       "      <td>0.352684</td>\n",
       "      <td>-0.625998</td>\n",
       "      <td>0.013681</td>\n",
       "      <td>0.015683</td>\n",
       "      <td>2.301685</td>\n",
       "      <td>1.196288</td>\n",
       "      <td>0.217099</td>\n",
       "      <td>0.402596</td>\n",
       "      <td>0.921664</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>650</th>\n",
       "      <td>-0.441560</td>\n",
       "      <td>0.310187</td>\n",
       "      <td>-0.559948</td>\n",
       "      <td>0.349136</td>\n",
       "      <td>0.332922</td>\n",
       "      <td>0.220886</td>\n",
       "      <td>0.826773</td>\n",
       "      <td>-0.257591</td>\n",
       "      <td>-1.961189</td>\n",
       "      <td>0.728867</td>\n",
       "      <td>...</td>\n",
       "      <td>0.420079</td>\n",
       "      <td>-0.213097</td>\n",
       "      <td>0.040658</td>\n",
       "      <td>0.010599</td>\n",
       "      <td>2.302685</td>\n",
       "      <td>1.130024</td>\n",
       "      <td>-0.060944</td>\n",
       "      <td>0.662074</td>\n",
       "      <td>1.033990</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>651</th>\n",
       "      <td>-2.807266</td>\n",
       "      <td>0.726236</td>\n",
       "      <td>2.737602</td>\n",
       "      <td>-0.933999</td>\n",
       "      <td>-2.413730</td>\n",
       "      <td>0.796625</td>\n",
       "      <td>-0.878071</td>\n",
       "      <td>-1.045044</td>\n",
       "      <td>1.249929</td>\n",
       "      <td>-0.960840</td>\n",
       "      <td>...</td>\n",
       "      <td>0.479636</td>\n",
       "      <td>-0.098230</td>\n",
       "      <td>0.053527</td>\n",
       "      <td>-0.408050</td>\n",
       "      <td>6.449524</td>\n",
       "      <td>-0.789890</td>\n",
       "      <td>-1.379371</td>\n",
       "      <td>0.171334</td>\n",
       "      <td>-1.636756</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>652</th>\n",
       "      <td>-0.258357</td>\n",
       "      <td>-0.519342</td>\n",
       "      <td>-0.035458</td>\n",
       "      <td>-0.117824</td>\n",
       "      <td>1.267125</td>\n",
       "      <td>-1.068542</td>\n",
       "      <td>-0.638446</td>\n",
       "      <td>0.352485</td>\n",
       "      <td>0.060428</td>\n",
       "      <td>0.332823</td>\n",
       "      <td>...</td>\n",
       "      <td>0.525568</td>\n",
       "      <td>0.084212</td>\n",
       "      <td>-0.001621</td>\n",
       "      <td>0.011866</td>\n",
       "      <td>4.218640</td>\n",
       "      <td>1.219725</td>\n",
       "      <td>-0.481149</td>\n",
       "      <td>-0.324351</td>\n",
       "      <td>-1.552562</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>653</th>\n",
       "      <td>-0.400077</td>\n",
       "      <td>-0.677461</td>\n",
       "      <td>0.778466</td>\n",
       "      <td>-0.303557</td>\n",
       "      <td>-0.630844</td>\n",
       "      <td>0.230737</td>\n",
       "      <td>0.015912</td>\n",
       "      <td>0.549293</td>\n",
       "      <td>1.123662</td>\n",
       "      <td>0.146946</td>\n",
       "      <td>...</td>\n",
       "      <td>-1.276798</td>\n",
       "      <td>-0.461654</td>\n",
       "      <td>0.205261</td>\n",
       "      <td>0.250664</td>\n",
       "      <td>4.007170</td>\n",
       "      <td>0.058501</td>\n",
       "      <td>1.058661</td>\n",
       "      <td>1.076857</td>\n",
       "      <td>1.589043</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>279863</th>\n",
       "      <td>-1.566487</td>\n",
       "      <td>-2.010494</td>\n",
       "      <td>-0.882850</td>\n",
       "      <td>0.697211</td>\n",
       "      <td>-2.064945</td>\n",
       "      <td>-5.587794</td>\n",
       "      <td>2.115795</td>\n",
       "      <td>-5.417424</td>\n",
       "      <td>-1.235123</td>\n",
       "      <td>-6.665177</td>\n",
       "      <td>...</td>\n",
       "      <td>0.537503</td>\n",
       "      <td>0.788395</td>\n",
       "      <td>0.292680</td>\n",
       "      <td>0.147968</td>\n",
       "      <td>5.966149</td>\n",
       "      <td>-1.927883</td>\n",
       "      <td>1.125653</td>\n",
       "      <td>-4.518331</td>\n",
       "      <td>1.749293</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>280143</th>\n",
       "      <td>0.442581</td>\n",
       "      <td>-1.326536</td>\n",
       "      <td>-1.413170</td>\n",
       "      <td>0.248525</td>\n",
       "      <td>-1.127396</td>\n",
       "      <td>-3.232153</td>\n",
       "      <td>2.858466</td>\n",
       "      <td>-3.096915</td>\n",
       "      <td>-0.792532</td>\n",
       "      <td>-5.210141</td>\n",
       "      <td>...</td>\n",
       "      <td>0.521875</td>\n",
       "      <td>0.739467</td>\n",
       "      <td>0.389152</td>\n",
       "      <td>0.186637</td>\n",
       "      <td>-0.273122</td>\n",
       "      <td>1.378559</td>\n",
       "      <td>1.289381</td>\n",
       "      <td>-5.004247</td>\n",
       "      <td>1.411850</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>280149</th>\n",
       "      <td>-1.120541</td>\n",
       "      <td>-0.003346</td>\n",
       "      <td>-2.234739</td>\n",
       "      <td>1.210158</td>\n",
       "      <td>-0.652250</td>\n",
       "      <td>-3.463891</td>\n",
       "      <td>1.794969</td>\n",
       "      <td>-2.775022</td>\n",
       "      <td>-0.418950</td>\n",
       "      <td>-4.057162</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.739695</td>\n",
       "      <td>0.471111</td>\n",
       "      <td>0.385107</td>\n",
       "      <td>0.194361</td>\n",
       "      <td>4.355310</td>\n",
       "      <td>-0.676143</td>\n",
       "      <td>1.126366</td>\n",
       "      <td>-2.213700</td>\n",
       "      <td>0.468308</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>281144</th>\n",
       "      <td>-0.840618</td>\n",
       "      <td>-2.943548</td>\n",
       "      <td>-2.208002</td>\n",
       "      <td>1.058733</td>\n",
       "      <td>-1.632333</td>\n",
       "      <td>-5.245984</td>\n",
       "      <td>1.933520</td>\n",
       "      <td>-5.030465</td>\n",
       "      <td>-1.127455</td>\n",
       "      <td>-6.416628</td>\n",
       "      <td>...</td>\n",
       "      <td>-0.328168</td>\n",
       "      <td>0.606116</td>\n",
       "      <td>0.884876</td>\n",
       "      <td>-0.253700</td>\n",
       "      <td>5.501262</td>\n",
       "      <td>-3.113832</td>\n",
       "      <td>0.585864</td>\n",
       "      <td>-5.399730</td>\n",
       "      <td>1.817092</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>281674</th>\n",
       "      <td>1.151147</td>\n",
       "      <td>-0.096695</td>\n",
       "      <td>0.223050</td>\n",
       "      <td>-0.068384</td>\n",
       "      <td>0.577829</td>\n",
       "      <td>-0.888722</td>\n",
       "      <td>0.491140</td>\n",
       "      <td>0.728903</td>\n",
       "      <td>0.380428</td>\n",
       "      <td>-1.948883</td>\n",
       "      <td>...</td>\n",
       "      <td>0.313267</td>\n",
       "      <td>-0.289617</td>\n",
       "      <td>0.002988</td>\n",
       "      <td>-0.015309</td>\n",
       "      <td>3.750233</td>\n",
       "      <td>1.991976</td>\n",
       "      <td>0.158476</td>\n",
       "      <td>-2.583441</td>\n",
       "      <td>0.408670</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>284160 rows × 30 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "              V5        V6        V7        V8        V9       V10       V11  \\\n",
       "649    -0.252045 -0.392240 -0.047177  0.041339 -0.069318  0.169913  0.947708   \n",
       "650    -0.441560  0.310187 -0.559948  0.349136  0.332922  0.220886  0.826773   \n",
       "651    -2.807266  0.726236  2.737602 -0.933999 -2.413730  0.796625 -0.878071   \n",
       "652    -0.258357 -0.519342 -0.035458 -0.117824  1.267125 -1.068542 -0.638446   \n",
       "653    -0.400077 -0.677461  0.778466 -0.303557 -0.630844  0.230737  0.015912   \n",
       "...          ...       ...       ...       ...       ...       ...       ...   \n",
       "279863 -1.566487 -2.010494 -0.882850  0.697211 -2.064945 -5.587794  2.115795   \n",
       "280143  0.442581 -1.326536 -1.413170  0.248525 -1.127396 -3.232153  2.858466   \n",
       "280149 -1.120541 -0.003346 -2.234739  1.210158 -0.652250 -3.463891  1.794969   \n",
       "281144 -0.840618 -2.943548 -2.208002  1.058733 -1.632333 -5.245984  1.933520   \n",
       "281674  1.151147 -0.096695  0.223050 -0.068384  0.577829 -0.888722  0.491140   \n",
       "\n",
       "             V12       V13       V14  ...       V25       V26       V27  \\\n",
       "649     0.417596 -0.798841  0.679509  ...  0.352684 -0.625998  0.013681   \n",
       "650    -0.257591 -1.961189  0.728867  ...  0.420079 -0.213097  0.040658   \n",
       "651    -1.045044  1.249929 -0.960840  ...  0.479636 -0.098230  0.053527   \n",
       "652     0.352485  0.060428  0.332823  ...  0.525568  0.084212 -0.001621   \n",
       "653     0.549293  1.123662  0.146946  ... -1.276798 -0.461654  0.205261   \n",
       "...          ...       ...       ...  ...       ...       ...       ...   \n",
       "279863 -5.417424 -1.235123 -6.665177  ...  0.537503  0.788395  0.292680   \n",
       "280143 -3.096915 -0.792532 -5.210141  ...  0.521875  0.739467  0.389152   \n",
       "280149 -2.775022 -0.418950 -4.057162  ... -0.739695  0.471111  0.385107   \n",
       "281144 -5.030465 -1.127455 -6.416628  ... -0.328168  0.606116  0.884876   \n",
       "281674  0.728903  0.380428 -1.948883  ...  0.313267 -0.289617  0.002988   \n",
       "\n",
       "             V28  Log Ammount        V1        V2        V3        V4  Class  \n",
       "649     0.015683     2.301685  1.196288  0.217099  0.402596  0.921664      0  \n",
       "650     0.010599     2.302685  1.130024 -0.060944  0.662074  1.033990      0  \n",
       "651    -0.408050     6.449524 -0.789890 -1.379371  0.171334 -1.636756      0  \n",
       "652     0.011866     4.218640  1.219725 -0.481149 -0.324351 -1.552562      0  \n",
       "653     0.250664     4.007170  0.058501  1.058661  1.076857  1.589043      0  \n",
       "...          ...          ...       ...       ...       ...       ...    ...  \n",
       "279863  0.147968     5.966149 -1.927883  1.125653 -4.518331  1.749293      1  \n",
       "280143  0.186637    -0.273122  1.378559  1.289381 -5.004247  1.411850      1  \n",
       "280149  0.194361     4.355310 -0.676143  1.126366 -2.213700  0.468308      1  \n",
       "281144 -0.253700     5.501262 -3.113832  0.585864 -5.399730  1.817092      1  \n",
       "281674 -0.015309     3.750233  1.991976  0.158476 -2.583441  0.408670      1  \n",
       "\n",
       "[284160 rows x 30 columns]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df = pd.concat([client_data, server_data], axis=1)\n",
    "df = df[-284160:]\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "from secretflow.data.split import train_test_split\n",
    "from secretflow_fl.ml.nn import SLModel\n",
    "\n",
    "spu = sf.SPU(sf.utils.testing.cluster_def([\"client\", \"server\"]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "from secretflow.utils.simulation.data.dataframe import create_df\n",
    "\n",
    "data = create_df(\n",
    "    source=df,\n",
    "    parts={client: (0, 25), server: (25, 29)},\n",
    "    axis=1,\n",
    "    shuffle=False,\n",
    ")\n",
    "label = create_df(\n",
    "    source=df,\n",
    "    parts={server: (29, 30)},\n",
    "    axis=1,\n",
    "    shuffle=False,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "label= <class 'secretflow.data.vertical.dataframe.VDataFrame'>,\n",
      "data = <class 'secretflow.data.vertical.dataframe.VDataFrame'>\n"
     ]
    }
   ],
   "source": [
    "print(f\"label= {type(label)},\\ndata = {type(data)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 确认VDataFrame存储无误\n",
    "# print(data.to_csv({server: \"server\"}))\n",
    "# print(data.to_csv({client: \"client\"}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(pid=1082796)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1082796)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1082286)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1082286)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1101560)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1101560)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1101559)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1101559)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1085372)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1085372)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(_run pid=1082286)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/sklearn/base.py:402: UserWarning: X has feature names, but StandardScaler was fitted without feature names\n",
      "\u001b[2m\u001b[36m(_run pid=1082286)\u001b[0m   warnings.warn(\n",
      "\u001b[2m\u001b[36m(_run pid=1085372)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/sklearn/base.py:402: UserWarning: X has feature names, but StandardScaler was fitted without feature names\n",
      "\u001b[2m\u001b[36m(_run pid=1085372)\u001b[0m   warnings.warn(\n",
      "\u001b[2m\u001b[36m(pid=1085404)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1085404)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n"
     ]
    }
   ],
   "source": [
    "from secretflow.preprocessing.scaler import MinMaxScaler, StandardScaler\n",
    "\n",
    "scaler = StandardScaler()\n",
    "data = scaler.fit_transform(data)\n",
    "# data = data.clip(-5,5)  # 由于sf中没有实现clip函数，因此先注释掉"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [],
   "source": [
    "random_state = 1234\n",
    "train_data, test_data = train_test_split(\n",
    "    data, train_size=0.8, random_state=random_state\n",
    ")\n",
    "train_label, test_label = train_test_split(\n",
    "    label, train_size=0.8, random_state=random_state\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "if not os.path.exists(f\"./model/\"):\n",
    "    os.makedirs(f\"./model/\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<secretflow.device.device.pyu.PYUObject at 0x7f35c2958b20>]"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_label.to_csv({server: \"./model/ys.csv\"})\n",
    "test_label.to_csv({server: \"./model/ys_test.csv\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "bopA4CdS_4-T"
   },
   "source": [
    "## Split Learning"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 实例化模型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "hidden_dim_1 = 16\n",
    "hidden_dim_2 = 4\n",
    "# Create FirstNet model\n",
    "client_builder = create_first_net(input_dim=25, hidden_dim=hidden_dim_1)\n",
    "\n",
    "# Create ZeroNet model\n",
    "server_zero_builder = create_zero_net(input_dim=4, hidden_dim=hidden_dim_2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "fuse_builder = create_fuse_model(\n",
    "    input_dim_1=hidden_dim_1, input_dim_2=hidden_dim_2, party_nums=2, output_dim=1\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "surrogate_builder = create_surrogate_model(\n",
    "    input_dim_1=hidden_dim_1, input_dim_2=hidden_dim_2, party_nums=2, output_dim=1\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "base_model_dict = {client: client_builder, server: server_zero_builder}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:Create proxy actor <class 'secretflow_fl.ml.nn.sl.backend.tensorflow.sl_base.PYUSLTFModel'> with party client.\n",
      "INFO:root:Create proxy actor <class 'secretflow_fl.ml.nn.sl.backend.tensorflow.sl_base.PYUSLTFModel'> with party server.\n"
     ]
    }
   ],
   "source": [
    "sl_model = SLModel(\n",
    "    base_model_dict=base_model_dict, device_y=server, model_fuse=fuse_builder\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 训练SplitNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:Create proxy actor <class 'secretflow_fl.ml.nn.sl.backend.tensorflow.sl_base.PYUSLTFModel'> with party client.\n",
      "INFO:root:Create proxy actor <class 'secretflow_fl.ml.nn.sl.backend.tensorflow.sl_base.PYUSLTFModel'> with party server.\n"
     ]
    }
   ],
   "source": [
    "from ExP_attack.labelleakage import ExPloitAttackSplitNNManager_sf\n",
    "\n",
    "manager = ExPloitAttackSplitNNManager_sf(device=\"cpu\")\n",
    "ExPloitAttackSplitNNAPI = manager.attach(SLModel)\n",
    "ExPloitattacksplitnn = ExPloitAttackSplitNNAPI(\n",
    "    base_model_dict=base_model_dict, device_y=server, model_fuse=fuse_builder\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_batch_size = 1024\n",
    "epochs_train = 10\n",
    "args_dict[\"batch_size\"] = train_batch_size"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:SL Train Params: {'self': <ExP_attack.labelleakage.ExPloitattack.attach_ExPloitattack_to_splitnn_sf.<locals>.ExPloitAttackSplitNNWrapper_sf object at 0x7f26d8345ee0>, 'x': VDataFrame(partitions={PYURuntime(client): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f36ac0bb430>), PYURuntime(server): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f36195fd580>)}, aligned=True), 'y': VDataFrame(partitions={PYURuntime(server): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f26d83cd100>)}, aligned=True), 'batch_size': 1024, 'epochs': 10, 'verbose': 1, 'callbacks': None, 'validation_data': (VDataFrame(partitions={PYURuntime(client): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f36195f4d90>), PYURuntime(server): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f26d83d4f70>)}, aligned=True), VDataFrame(partitions={PYURuntime(server): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f26d83cd1c0>)}, aligned=True)), 'shuffle': False, 'sample_weight': None, 'validation_freq': 1, 'dp_spent_step_freq': None, 'dataset_builder': None, 'audit_log_params': {}, 'random_seed': 21715, 'save_path': '', 'audit_log_dir': None}\n",
      "\u001b[2m\u001b[36m(pid=1102789)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1102789)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1102854)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1102854)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1102919)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1102919)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1102992)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1102992)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:50:59,400 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29477847040; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m 2023-10-07 20:51:00.070554: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m 2023-10-07 20:51:00.145151: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m 2023-10-07 20:51:00.099792: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m Model: \"sequential\"\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m _________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m  Layer (type)                Output Shape              Param #   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m =================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m  dense (Dense)               (None, 8)                 208       \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m                                                                  \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m  dense_1 (Dense)             (None, 16)                144       \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m                                                                  \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m =================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m Total params: 352\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m Trainable params: 352\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m Non-trainable params: 0\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102789)\u001b[0m _________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m Model: \"sequential\"\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m _________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m  Layer (type)                Output Shape              Param #   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m =================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m  dense (Dense)               (None, 8)                 208       \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m                                                                  \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m  dense_1 (Dense)             (None, 16)                144       \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m                                                                  \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m =================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m Total params: 352\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m Trainable params: 352\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m Non-trainable params: 0\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102919)\u001b[0m _________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m Model: \"sequential\"\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m _________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m  Layer (type)                Output Shape              Param #   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m =================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m  dense (Dense)               (None, 4)                 20        \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m                                                                  \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m =================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m Total params: 20\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m Trainable params: 20\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m Non-trainable params: 0\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m _________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m Model: \"model\"\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m __________________________________________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m  Layer (type)                   Output Shape         Param #     Connected to                     \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m ==================================================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m  input_2 (InputLayer)           [(None, 16)]         0           []                               \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m                                                                                                   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m  input_3 (InputLayer)           [(None, 4)]          0           []                               \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m                                                                                                   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m  concatenate (Concatenate)      (None, 20)           0           ['input_2[0][0]',                \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m                                                                   'input_3[0][0]']                \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m                                                                                                   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m  dense_1 (Dense)                (None, 1)            21          ['concatenate[0][0]']            \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m                                                                                                   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m ==================================================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m Total params: 21\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m Trainable params: 21\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m Non-trainable params: 0\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102854)\u001b[0m __________________________________________________________________________________________________\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m 2023-10-07 20:51:00.372924: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m Model: \"sequential\"\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m _________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m  Layer (type)                Output Shape              Param #   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m =================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m  dense (Dense)               (None, 4)                 20        \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m                                                                  \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m =================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m Total params: 20\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m Trainable params: 20\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m Non-trainable params: 0\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m _________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m Model: \"model\"\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m __________________________________________________________________________________________________\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m  Layer (type)                   Output Shape         Param #     Connected to                     \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m ==================================================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m  input_2 (InputLayer)           [(None, 16)]         0           []                               \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m                                                                                                   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m  input_3 (InputLayer)           [(None, 4)]          0           []                               \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m                                                                                                   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m  concatenate (Concatenate)      (None, 20)           0           ['input_2[0][0]',                \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m                                                                   'input_3[0][0]']                \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m                                                                                                   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m  dense_1 (Dense)                (None, 1)            21          ['concatenate[0][0]']            \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m                                                                                                   \n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m ==================================================================================================\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m Total params: 21\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m Trainable params: 21\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m Non-trainable params: 0\n",
      "\u001b[2m\u001b[36m(PYUSLTFModel pid=1102992)\u001b[0m __________________________________________________________________________________________________\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "  1%|          | 2/222 [00:00<01:20,  2.73it/s]\u001b[2m\u001b[36m(_run pid=1082796)\u001b[0m 2023-10-07 20:51:04.633139: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      " 45%|████▍     | 99/222 [00:06<00:03, 33.59it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:51:09,407 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29477642240; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[36m(_run pid=1085404)\u001b[0m 2023-10-07 20:51:12.169939: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "100%|██████████| 222/222 [00:16<00:00, 13.41it/s, epoch: 1/10 -  train_loss:0.13633137941360474  train_accuracy:0.9961948990821838  train_auc_1:0.38060346245765686  val_loss:0.023318707942962646  val_accuracy:0.9984691739082336  val_auc_1:0.5998096466064453 ]\n",
      "  0%|          | 0/222 [00:00<?, ?it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:51:19,413 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29477425152; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[36m(_run pid=1085372)\u001b[0m 2023-10-07 20:51:20.667638: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "100%|██████████| 222/222 [00:11<00:00, 20.08it/s, epoch: 2/10 -  train_loss:0.014067494310438633  train_accuracy:0.9982184171676636  train_auc_1:0.8157362937927246  val_loss:0.008083485998213291  val_accuracy:0.9986627101898193  val_auc_1:0.8627776503562927 ]\n",
      " 17%|█▋        | 37/222 [00:01<00:06, 27.67it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:51:29,423 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29477089280; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      " 45%|████▌     | 101/222 [00:03<00:05, 21.75it/s]\u001b[2m\u001b[36m(_run pid=1082286)\u001b[0m 2023-10-07 20:51:35.237217: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "100%|█████████▉| 221/222 [00:10<00:00, 31.17it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:51:39,433 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29476790272; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "100%|██████████| 222/222 [00:11<00:00, 19.57it/s, epoch: 3/10 -  train_loss:0.006838476285338402  train_accuracy:0.9986451268196106  train_auc_1:0.8960989117622375  val_loss:0.005792135372757912  val_accuracy:0.9989794492721558  val_auc_1:0.8934713006019592 ]\n",
      "100%|██████████| 222/222 [00:07<00:00, 28.99it/s, epoch: 4/10 -  train_loss:0.005200130864977837  train_accuracy:0.9989838600158691  train_auc_1:0.9210806488990784  val_loss:0.005066062323749065  val_accuracy:0.9991729855537415  val_auc_1:0.9206399321556091 ]\n",
      " 39%|███▉      | 87/222 [00:02<00:03, 39.47it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:51:49,441 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29476417536; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "100%|██████████| 222/222 [00:07<00:00, 31.06it/s, epoch: 5/10 -  train_loss:0.00454473402351141  train_accuracy:0.9991158246994019  train_auc_1:0.9306226372718811  val_loss:0.004730305168777704  val_accuracy:0.9992433786392212  val_auc_1:0.9223645329475403 ]\n",
      " 44%|████▍     | 98/222 [00:02<00:03, 35.27it/s]\u001b[2m\u001b[36m(pid=1082522)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1082522)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1084122)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1084122)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      " 46%|████▌     | 102/222 [00:03<00:12,  9.47it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:51:59,447 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29476007936; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[36m(_run pid=1084122)\u001b[0m 2023-10-07 20:52:03.038975: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "100%|██████████| 222/222 [00:13<00:00, 17.00it/s, epoch: 6/10 -  train_loss:0.0041607581079006195  train_accuracy:0.9992433786392212  train_auc_1:0.9363973736763  val_loss:0.004527427721768618  val_accuracy:0.9993489384651184  val_auc_1:0.917296290397644 ]\n",
      "  0%|          | 0/222 [00:00<?, ?it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:52:09,454 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29475770368; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[36m(_run pid=1082522)\u001b[0m 2023-10-07 20:52:11.753747: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "100%|██████████| 222/222 [00:11<00:00, 19.29it/s, epoch: 7/10 -  train_loss:0.003918141592293978  train_accuracy:0.9993137717247009  train_auc_1:0.9392414093017578  val_loss:0.004397901240736246  val_accuracy:0.9993841648101807  val_auc_1:0.9233108162879944 ]\n",
      " 10%|▉         | 22/222 [00:00<00:04, 41.90it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:52:19,461 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29475450880; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      " 89%|████████▊ | 197/222 [00:05<00:00, 33.96it/s]\u001b[2m\u001b[36m(pid=1080544)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1080544)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1085578)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1085578)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1083545)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1083545)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1082341)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1082341)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1087451)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1087451)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1082692)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1082692)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1082329)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1082329)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1079981)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1079981)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1081999)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1081999)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      "\u001b[2m\u001b[36m(pid=1089757)\u001b[0m /home/kyzhang/anaconda3/envs/exploit/lib/python3.8/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5\n",
      "\u001b[2m\u001b[36m(pid=1089757)\u001b[0m   warnings.warn(f\"A NumPy version >={np_minversion} and <{np_maxversion}\"\n",
      " 91%|█████████ | 201/222 [00:07<00:02,  7.18it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:52:29,471 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29474742272; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[36m(_run pid=1079981)\u001b[0m 2023-10-07 20:52:30.208998: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "100%|██████████| 222/222 [00:12<00:00, 18.12it/s, epoch: 8/10 -  train_loss:0.003748086281120777  train_accuracy:0.9993621706962585  train_auc_1:0.9394967555999756  val_loss:0.004307356663048267  val_accuracy:0.9993841648101807  val_auc_1:0.9234800338745117 ]\n",
      " 45%|████▌     | 100/222 [00:02<00:03, 32.86it/s]\u001b[2m\u001b[36m(_run pid=1082341)\u001b[0m 2023-10-07 20:52:37.726297: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      " 68%|██████▊   | 152/222 [00:08<00:02, 27.74it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:52:39,478 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29474250752; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "100%|██████████| 222/222 [00:11<00:00, 19.80it/s, epoch: 9/10 -  train_loss:0.0036056421231478453  train_accuracy:0.999397337436676  train_auc_1:0.9445409774780273  val_loss:0.0042426264844834805  val_accuracy:0.9994017481803894  val_auc_1:0.9064751863479614 ]\n",
      "  0%|          | 0/222 [00:00<?, ?it/s]\u001b[2m\u001b[36m(_run pid=1089757)\u001b[0m 2023-10-07 20:52:45.935109: E tensorflow/compiler/xla/stream_executor/cuda/cuda_driver.cc:267] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected\n",
      "INFO:jax._src.xla_bridge:Unable to initialize backend 'cuda': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'\n",
      "INFO:jax._src.xla_bridge:Unable to initialize backend 'rocm': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'\n",
      "INFO:jax._src.xla_bridge:Unable to initialize backend 'tpu': INVALID_ARGUMENT: TpuPlatform is not available.\n",
      "INFO:jax._src.xla_bridge:Unable to initialize backend 'plugin': xla_extension has no attributes named get_plugin_device_client. Compile TensorFlow with //tensorflow/compiler/xla/python:enable_plugin_device set to true (defaults to false) to enable this.\n",
      "WARNING:jax._src.xla_bridge:No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)\n",
      "\u001b[2m\u001b[36m(_run pid=1079981)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'cuda': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'\n",
      "\u001b[2m\u001b[36m(_run pid=1079981)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'rocm': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'\n",
      "\u001b[2m\u001b[36m(_run pid=1079981)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'tpu': INVALID_ARGUMENT: TpuPlatform is not available.\n",
      "\u001b[2m\u001b[36m(_run pid=1079981)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'plugin': xla_extension has no attributes named get_plugin_device_client. Compile TensorFlow with //tensorflow/compiler/xla/python:enable_plugin_device set to true (defaults to false) to enable this.\n",
      "\u001b[2m\u001b[36m(_run pid=1079981)\u001b[0m WARNING:jax._src.xla_bridge:No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)\n",
      "\u001b[2m\u001b[36m(_run pid=1089757)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'cuda': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'\n",
      "\u001b[2m\u001b[36m(_run pid=1089757)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'rocm': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'\n",
      "\u001b[2m\u001b[36m(_run pid=1089757)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'tpu': INVALID_ARGUMENT: TpuPlatform is not available.\n",
      "\u001b[2m\u001b[36m(_run pid=1089757)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'plugin': xla_extension has no attributes named get_plugin_device_client. Compile TensorFlow with //tensorflow/compiler/xla/python:enable_plugin_device set to true (defaults to false) to enable this.\n",
      "\u001b[2m\u001b[36m(_run pid=1089757)\u001b[0m WARNING:jax._src.xla_bridge:No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)\n",
      " 14%|█▍        | 31/222 [00:06<00:18, 10.52it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:52:49,487 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29473009664; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      " 45%|████▌     | 100/222 [00:13<00:10, 11.72it/s]\u001b[2m\u001b[36m(_run pid=1082341)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'cuda': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'\n",
      "\u001b[2m\u001b[36m(_run pid=1082341)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'rocm': module 'jaxlib.xla_extension' has no attribute 'GpuAllocatorConfig'\n",
      "\u001b[2m\u001b[36m(_run pid=1082341)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'tpu': INVALID_ARGUMENT: TpuPlatform is not available.\n",
      "\u001b[2m\u001b[36m(_run pid=1082341)\u001b[0m INFO:jax._src.xla_bridge:Unable to initialize backend 'plugin': xla_extension has no attributes named get_plugin_device_client. Compile TensorFlow with //tensorflow/compiler/xla/python:enable_plugin_device set to true (defaults to false) to enable this.\n",
      "\u001b[2m\u001b[36m(_run pid=1082341)\u001b[0m WARNING:jax._src.xla_bridge:No GPU/TPU found, falling back to CPU. (Set TF_CPP_MIN_LOG_LEVEL=0 and rerun for more info.)\n",
      " 61%|██████▏   | 136/222 [00:17<00:07, 11.08it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:52:59,498 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29472628736; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "100%|█████████▉| 221/222 [00:25<00:00, 11.82it/s]\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:53:09,505 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29472264192; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "100%|██████████| 222/222 [00:28<00:00,  7.88it/s, epoch: 10/10 -  train_loss:0.0034850607626140118  train_accuracy:0.9994193315505981  train_auc_1:0.9446365833282471  val_loss:0.004182739183306694  val_accuracy:0.9994017481803894  val_auc_1:0.9122677445411682 ]\n"
     ]
    }
   ],
   "source": [
    "history = ExPloitattacksplitnn.fit_save(\n",
    "    train_data,\n",
    "    train_label,\n",
    "    validation_data=(test_data, test_label),\n",
    "    epochs=epochs_train,\n",
    "    batch_size=train_batch_size,\n",
    "    shuffle=False,\n",
    "    verbose=1,\n",
    "    validation_freq=1,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 评估SplitNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAHFCAYAAAAaD0bAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABPuklEQVR4nO3de1xUdf4/8NeZO3eRqyAiCiXmHcpFo3QrTDdXyjay0tyslm6G/NxvKtrFVtm0kloD19JaK41ttdZtqaSLZmoXFS03MjUVRZCLylVmmJnz+2OYkXEG5DJw5vJ6Ph7zYOYzn3PmPdhjee3nfD6fI4iiKIKIiIjIg8ikLoCIiIiotzEAERERkcdhACIiIiKPwwBEREREHocBiIiIiDwOAxARERF5HAYgIiIi8jgMQERERORxGICIiIjI4zAAEZFDvPXWWxAEAYIgYPv27Tbvi6KI2NhYCIKACRMmOPSzBUHAs88+2+njTpw4AUEQ8NZbbzmkHxG5DgYgInIoPz8/rFu3zqZ9x44dOHbsGPz8/CSoiojIGgMQETlUWloaNm/ejNraWqv2devWISkpCQMGDJCoMiKiSxiAiMihZsyYAQDYtGmTpa2mpgabN2/GAw88YPeYc+fO4dFHH0VkZCRUKhUGDRqErKwsaLVaq361tbV46KGHEBQUBF9fX9x666345Zdf7J7zyJEjuOeeexAaGgq1Wo34+Hi89tprDvqWJl9//TVuuukm+Pn5wdvbG+PGjcN///tfqz6NjY2YP38+YmJioNFo0LdvXyQmJlr9fn799VfcfffdiIiIgFqtRlhYGG666SYcOHDAofUS0SUKqQsgIvfi7++PO++8E+vXr8ef/vQnAKYwJJPJkJaWhpycHKv+TU1NmDhxIo4dO4bnnnsOI0aMwM6dO5GdnY0DBw5YAoUoikhNTcXu3bvx9NNP49prr8WuXbswefJkmxp++uknjBs3DgMGDMBLL72E8PBwfPrpp5g7dy6qqqrwzDPPdPt77tixA7fccgtGjBiBdevWQa1WIzc3F1OnTsWmTZuQlpYGAMjMzMTbb7+Nv/zlLxg9ejQaGhpw6NAhVFdXW841ZcoUGAwGrFixAgMGDEBVVRV2796NCxcudLtOImqDSETkAG+++aYIQPz+++/FL7/8UgQgHjp0SBRFUbz22mvF2bNni6Ioitdcc4144403Wo5bs2aNCED85z//aXW+F154QQQgbtu2TRRFUfz4449FAOIrr7xi1W/ZsmUiAPGZZ56xtE2aNEns37+/WFNTY9X38ccfFzUajXju3DlRFEXx+PHjIgDxzTffbPe72ev3m9/8RgwNDRXr6uosbXq9Xhw2bJjYv39/0Wg0iqIoisOGDRNTU1PbPHdVVZUIQMzJyWm3BiJyLF4CIyKHu/HGGzF48GCsX78eP/74I77//vs2L3998cUX8PHxwZ133mnVPnv2bADA559/DgD48ssvAQD33nuvVb977rnH6nVTUxM+//xz3H777fD29oZer7c8pkyZgqamJnzzzTfd+n4NDQ349ttvceedd8LX19fSLpfLMXPmTJw+fRqHDx8GAFx33XX4+OOPsWDBAmzfvh0XL160Olffvn0xePBgrFy5Ei+//DKKiopgNBq7VR8RXRkDEBE5nCAI+OMf/4h33nkHa9aswVVXXYXk5GS7faurqxEeHg5BEKzaQ0NDoVAoLJeKqquroVAoEBQUZNUvPDzc5nx6vR5/+9vfoFQqrR5TpkwBAFRVVXXr+50/fx6iKKJfv34270VERFjqAIBXX30VTz31FD788ENMnDgRffv2RWpqKo4cOQLA9Lv6/PPPMWnSJKxYsQJjxoxBSEgI5s6di7q6um7VSURtYwAioh4xe/ZsVFVVYc2aNfjjH//YZr+goCCcPXsWoihatVdUVECv1yM4ONjST6/XW82dAYDy8nKr14GBgZDL5Zg9eza+//57uw9zEOqqwMBAyGQylJWV2bx35swZALDU7ePjg+eeew4///wzysvLkZeXh2+++QZTp061HBMdHY1169ahvLwchw8fxrx585Cbm4s///nP3aqTiNrGAEREPSIyMhJ//vOfMXXqVNx///1t9rvppptQX1+PDz/80Kp9w4YNlvcBYOLEiQCAd99916rfxo0brV57e3tj4sSJKCoqwogRI5CYmGjzuHwUqbN8fHwwduxYbNmyxeqSltFoxDvvvIP+/fvjqquusjkuLCwMs2fPxowZM3D48GE0Njba9LnqqquwePFiDB8+HPv37+9WnUTUNq4CI6Ie89e//vWKfWbNmoXXXnsN999/P06cOIHhw4fj66+/xvLlyzFlyhTcfPPNAICUlBTccMMN+L//+z80NDQgMTERu3btwttvv21zzldeeQXXX389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hgGIiNzCkiVLMH36dBw8eBD33XcfZsyYgeLiYgBAY2Mjbr31VgQGBuL777/H+++/j88++8wq4OTl5eGxxx7Dww8/jB9//BFbt25FbGys1Wc899xzuOuuu/DDDz9gypQpuPfee3Hu3Lle/Z5E5CAiEZGTu//++0W5XC76+PhYPZYuXSqKoigCENPT062OGTt2rPjII4+IoiiKa9euFQMDA8X6+nrL+//9739FmUwmlpeXi6IoihEREWJWVlabNQAQFy9ebHldX18vCoIgfvzxxw77nkTUezgHiIhcwsSJE5GXl2fV1rdvX8vzpKQkq/eSkpJw4MABAEBxcTFGjhwJHx8fy/vjx4+H0WjE4cOHIQgCzpw5g5tuuqndGkaMGGF57uPjAz8/P1RUVHT1KxGRhBiAiMgl+Pj42FySuhJBEAAAoihantvr4+Xl1aHzKZVKm2ONRmOnaiIi58A5QETkFr755hub10OGDAEADB06FAcOHEBDQ4Pl/V27dkEmk+Gqq66Cn58fBg4ciM8//7xXayYi6XAEiIhcglarRXl5uVWbQqFAcHAwAOD9999HYmIirr/+erz77rv47rvvsG7dOgDAvffei2eeeQb3338/nn32WVRWVuKJJ57AzJkzERYWBgB49tlnkZ6ejtDQUEyePBl1dXXYtWsXnnjiid79okTUKxiAiMglfPLJJ+jXr59V29VXX42ff/4ZgGmF1nvvvYdHH30U4eHhePfddzF06FAAgLe3Nz799FM8+eSTuPbaa+Ht7Y3p06fj5Zdftpzr/vvvR1NTE1atWoX58+cjODgYd955Z+99QSLqVYIoiqLURRARdYcgCPjggw+QmpoqdSlE5CI4B4iIiIg8DgMQEREReRzOASIil8cr+UTUWRwBIiIiIo/DAEREREQehwGIiIiIPA4DEBEREXkcBiAiIiLyOAxARERE5HEYgIiIiMjjMAARERGRx2EAIiIiIo/z/wGWxcwR89wqlQAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the change of loss during training\n",
    "plt.plot(history[\"train_loss\"])\n",
    "plt.plot(history[\"val_loss\"])\n",
    "plt.title(\"Model loss\")\n",
    "plt.ylabel(\"Loss\")\n",
    "plt.xlabel(\"Epoch\")\n",
    "plt.legend([\"Train\", \"Val\"], loc=\"upper right\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAlIAAAHFCAYAAAA5VBcVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABuF0lEQVR4nO3deVyU5f7/8dcwDDDsKIKACkimpOWGubVZJ02zo2Zlm8elY8eTduLYamqZlXbqp9W30tLSXCo9Hk/aXman0ixRXNIsd0VJRJBFdpi5f3+MjE6oCaHDwPv5eMxD5ppr7vnMYM67677u6zIZhmEgIiIiItXm5e4CRERERDyVgpSIiIhIDSlIiYiIiNSQgpSIiIhIDSlIiYiIiNSQgpSIiIhIDSlIiYiIiNSQgpSIiIhIDSlIiYiIiNSQgpSI1Njbb7+NyWTCZDLx9ddfV3ncMAwuuugiTCYT11xzTa2+tslkYvLkydV+3v79+zGZTLz99tu1Wo+INEwKUiLyhwUFBfHWW29Vaf/mm2/Ys2cPQUFBbqhKROT8U5ASkT9syJAhLFu2jPz8fJf2t956i+7du9OiRQs3VdZwlJeXU1FR4e4yRBocBSkR+cPuuOMOAN577z1nW15eHsuWLWPkyJGnfc6xY8e47777iImJwcfHh5YtWzJhwgRKS0td+uXn5zNq1CgaN25MYGAgN9xwAzt37jztMXft2sWdd95JREQEvr6+JCYm8tprr9XoPZWUlPDggw/SoUMHQkJCaNSoEd27d2fFihVV+trtdl555RU6dOiA1WolNDSUbt268cEHH7j0e/fdd+nevTuBgYEEBgbSoUMHl5G8uLg4hg8fXuX411xzjcup0a+//hqTycTChQt58MEHiYmJwdfXl927d3P06FHuu+8+LrnkEgIDA4mIiODaa69l9erVVY5bWlrKlClTSExMxM/Pj8aNG9OrVy/Wrl0LwHXXXUebNm347d72ladsb7zxxup8pCL1kre7CxARzxccHMwtt9zC3Llz+dvf/gY4QpWXlxdDhgzhpZdeculfUlJCr1692LNnD0899RSXXXYZq1evZtq0aWzevJmPP/4YcHxhDxw4kLVr1/LEE0/QpUsXvvvuO/r27Vulhu3bt9OjRw9atGjB9OnTadq0KZ9//jn/+Mc/yMrK4sknn6zWeyotLeXYsWM89NBDxMTEUFZWxpdffsnNN9/MvHnz+Mtf/uLsO3z4cBYtWsQ999zDlClT8PHxYePGjezfv9/Z54knnuDpp5/m5ptv5sEHHyQkJIRt27Zx4MCBatV1qvHjx9O9e3def/11vLy8iIiI4OjRowA8+eSTNG3alIKCAt5//32uueYaVq1a5QxkFRUV9O3bl9WrV5OcnMy1115LRUUFP/zwA2lpafTo0YMHHniAAQMGsGrVKv70pz85X/fTTz9lz549/N///V+NaxepNwwRkRqaN2+eARjr1683/ve//xmAsW3bNsMwDKNLly7G8OHDDcMwjLZt2xpXX32183mvv/66ARj//ve/XY73r3/9ywCML774wjAMw/j0008NwHj55Zdd+j377LMGYDz55JPOtj59+hjNmjUz8vLyXPqOHTvW8PPzM44dO2YYhmHs27fPAIx58+ZV671WVFQY5eXlxj333GN07NjR2f7tt98agDFhwoQzPnfv3r2G2Ww27rrrrrO+RmxsrDFs2LAq7VdffbXL51f5WV911VXnXPd1111nDBo0yNm+YMECAzDmzJlzxufabDajZcuWxoABA1za+/btayQkJBh2u/13X1+kvtOpPRGpFVdffTUJCQnMnTuXrVu3sn79+jOe1vvqq68ICAjglltucWmvPK21atUqAP73v/8BcNddd7n0u/POO13ul5SUsGrVKgYNGoS/vz8VFRXOW79+/SgpKeGHH36o9ntaunQpPXv2JDAwEG9vbywWC2+99RY///yzs8+nn34KwJgxY854nJUrV2Kz2c7apyYGDx582vbXX3+dTp064efn56x71apVVer28/M74+8IwMvLi7Fjx/LRRx+RlpYGwJ49e/jss8+47777MJlMtfp+RDyRgpSI1AqTycSIESNYtGgRr7/+OhdffDFXXnnlaftmZ2fTtGnTKl/EEREReHt7k52d7ezn7e1N48aNXfo1bdq0yvEqKip45ZVXsFgsLrd+/foBkJWVVa3389///pfbbruNmJgYFi1axPfff+8MhyUlJc5+R48exWw2V6npVJWn25o1a1atGn5PVFRUlbYZM2bw97//na5du7Js2TJ++OEH1q9fzw033EBxcbFLTdHR0Xh5nf1rYOTIkVitVl5//XUAXnvtNaxW61kDmEhDojlSIlJrhg8fzhNPPMHrr7/Os88+e8Z+jRs3Zt26dRiG4RKmMjMzqaioIDw83NmvoqKC7OxslzCVkZHhcrywsDDMZjNDhw4946hPfHx8td7LokWLiI+PZ8mSJS41/nYyfJMmTbDZbGRkZJw22FT2ATh06BDNmzc/42v6+flVOT44QmDlZ3Kq040ILVq0iGuuuYZZs2a5tB8/frxKTWvWrMFut581TIWEhDBs2DDefPNNHnroIebNm8edd95JaGjoGZ8j0pBoREpEak1MTAwPP/wwN910E8OGDTtjv+uuu46CggKWL1/u0r5gwQLn4wC9evUC4J133nHp9+6777rc9/f3p1evXmzatInLLruMpKSkKrffjmr9HpPJhI+Pj0tYycjIqHLVXuXE998Gl1P17t0bs9l81j7guGrvxx9/dGnbuXMnO3bsqFbdvr6+Lm0//vgj33//fZW6S0pKzmlh0soJ+7fccgu5ubmMHTv2nOsRqe80IiUiteq555773T5/+ctfeO211xg2bBj79+/n0ksvZc2aNUydOpV+/fo5rxDr3bs3V111FY888giFhYUkJSXx3XffsXDhwirHfPnll7niiiu48sor+fvf/05cXBzHjx9n9+7dfPjhh3z11VfVeh/9+/fnv//9L/fddx+33HILBw8e5OmnnyYqKopdu3Y5+1155ZUMHTqUZ555hiNHjtC/f398fX3ZtGkT/v7+3H///cTFxfH444/z9NNPU1xczB133EFISAjbt28nKyuLp556CoChQ4dy9913c9999zF48GAOHDjA888/7xzROte6n376aZ588kmuvvpqduzYwZQpU4iPj3dZZ+qOO+5g3rx5jB49mh07dtCrVy/sdjvr1q0jMTGR22+/3dn34osv5oYbbuDTTz/liiuuoH379tX6LEXqNXfPdhcRz3XqVXtn89ur9gzDMLKzs43Ro0cbUVFRhre3txEbG2uMHz/eKCkpcemXm5trjBw50ggNDTX8/f2N66+/3vjll1+qXLVnGI4r8kaOHGnExMQYFovFaNKkidGjRw/jmWeecenDOV6199xzzxlxcXGGr6+vkZiYaMyZM8d48sknjd/+02mz2YwXX3zRaNeuneHj42OEhIQY3bt3Nz788EOXfgsWLDC6dOli+Pn5GYGBgUbHjh1d6rDb7cbzzz9vtGzZ0vDz8zOSkpKMr7766oxX7S1durRKzaWlpcZDDz1kxMTEGH5+fkanTp2M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6dK+cuVKevTo4aaqGi7DMBg7diz//e9/+eqrr4iPj3d3SQ3addddx9atW9m8ebPzlpSUxF133cXmzZsVotygZ8+eVZYE2blzJ7GxsW6qqGErKirCy8v1a99sNmv5gz9II1IeZty4cQwdOpSkpCS6d+/O7NmzSUtLY/To0e4urcEZM2YM7777LitWrCAoKMg5UhgSEoLVanVzdQ1PUFBQlflpAQEBNG7cWPPW3OSf//wnPXr0YOrUqdx2222kpKQwe/ZsZs+e7e7SGqSbbrqJZ599lhYtWtC2bVs2bdrEjBkzGDlypLtL82ha/sADzZw5k+eff57Dhw/Trl07XnzxRV1u7wZnmpc2b948hg8ffmGLkdO65pprtPyBm3300UeMHz+eXbt2ER8fz7hx4xg1apS7y2qQjh8/zqRJk3j//ffJzMwkOjqaO+64gyeeeAIfHx93l+exFKREREREakhzpERERERqSEFKREREpIYUpERERERqSEFKREREpIYUpERERERqSEFKREREpIYUpERERERqSEFKROQCMplMLF++3N1liEgtUZASkQZj+PDhmEymKrcbbrjB3aWJiIfSXnsi0qDccMMNzJs3z6XN19fXTdWIiKfTiJSINCi+vr40bdrU5RYWFgY4TrvNmjWLvn37YrVaiY+PZ+nSpS7P37p1K9deey1Wq5XGjRtz7733UlBQ4NJn7ty5tG3bFl9fX6Kiohg7dqzL41lZWQwaNAh/f39atWrFBx98cH7ftIicNwpSIiKnmDRpEoMHD2bLli3cfffd3HHHHfz8888AFBUVccMNNxAWFsb69etZunQpX375pUtQmjVrFmPGjOHee+9l69atfPDBB1x00UUur/HUU09x22238eOPP9KvXz/uuusujh07dkHfp4jUEkNEpIEYNmyYYTabjYCAAJfblClTDMMwDMAYPXq0y3O6du1q/P3vfzcMwzBmz55thIWFGQUFBc7HP/74Y8PLy8vIyMgwDMMwoqOjjQkTJpyxBsCYOHGi835BQYFhMpmMTz/9tNbep4hcOJojJSINSq9evZg1a5ZLW6NGjZw/d+/e3eWx7t27s3nzZgB+/vln2rdvT0BAgPPxnj17Yrfb2bFjByaTiV9//ZXrrrvurDVcdtllzp8DAgIICgoiMzOzpm9JRNxIQUpEGpSAgIAqp9p+j8lkAsAwDOfPp+tjtVrP6XgWi6XKc+12e7VqEpG6QXOkRERO8cMPP1S536ZNGwAuueQSNm/eTGFhofPx7777Di8vLy6++GKCgoKIi4tj1apVF7RmEXEfjUiJSINSWlpKRkaGS5u3tzfh4eEALF26lKSkJK644greeecdUlJSeOuttwC46667ePLJJxk2bBiTJ0/m6NGj3H///QwdOpTIyEgAJk+ezOjRo4mIiKBv374cP36c7777jvvvv//CvlERuSAUpESkQfnss8+IiopyaWvdujW//PIL4LiibvHixdx33300bdqUd955h0suuQQAf39/Pv/8cx544AG6dOmCv78/gwcPZsaMGc5jDRs2jJKSEl588UUeeughwsPDueWWWy7cGxSRC8pkGIbh7iJEROoCk8nE+++/z8CBA91dioh4CM2REhEREakhBSkRERGRGtIcKRGREzTTQUSqSyNSIiIiIjWkICUiIiJSQwpSIiIiIjWkICUiIiJSQwpSIiIiIjWkICUiIiJSQwpSIiIiIjWkICUiIiJSQwpSIiIiIjX0/wGHKVbiYpZzJAAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the change of accuracy during training\n",
    "plt.plot(history[\"train_accuracy\"])\n",
    "plt.plot(history[\"val_accuracy\"])\n",
    "plt.title(\"Model accuracy\")\n",
    "plt.ylabel(\"Accuracy\")\n",
    "plt.xlabel(\"Epoch\")\n",
    "plt.legend([\"Train\", \"Val\"], loc=\"upper left\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAHFCAYAAAAOmtghAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABeFElEQVR4nO3dd3hT9f4H8HeSpkn3pJNSym4ZAi0iS0Sw7CH6AxXZKLgQEb0iCheuWifWq4IiS7ygvV68XhUEqiAyZchu2aPYQWlLm860Tb6/P9KkDR0kbdK0yfv1PHmSnJxz8knjvXnzXUcihBAgIiIishNSWxdAREREZEkMN0RERGRXGG6IiIjIrjDcEBERkV1huCEiIiK7wnBDREREdoXhhoiIiOwKww0RERHZFYYbIiIisisMN0QNtH79ekgkEkgkEvz222/VXhdCoF27dpBIJLjvvvss+t4SiQR///vfzT7u6tWrkEgkWL9+vcnHnDp1ChKJBHK5HOnp6Wa/Z2OYNm0a3N3da33d3d0d06ZNs+h7tm7d2uLnrItarcYnn3yC/v37w8fHB87OzggNDcWECROwe/fuRquDqCljuCGyEA8PD6xZs6ba9t27d+PSpUvw8PCwQVWWs3r1agBAeXk5NmzYYONqHFNWVhb69euH+fPno0uXLli/fj1+/fVXfPDBB5DJZBg8eDBOnDhh6zKJbI7hhshCJk6ciM2bN0OlUhltX7NmDfr06YNWrVrZqLKGU6vV2LhxI+666y6EhoZi7dq1Jh9bXFxsxcrsi0ajgVqtrvX1KVOm4MSJE9i2bRs+++wzjB07FgMGDMAjjzyCr7/+GgcOHICPj49FauH3Rs0Zww2RhTz66KMAgK+//tqwLS8vD5s3b8aMGTNqPCYnJwdPP/00QkND4ezsjDZt2mDRokXVfuBUKhWeeOIJ+Pn5wd3dHcOGDcP58+drPOeFCxfw2GOPISAgAAqFApGRkfj0008b9Nm+//57ZGdnY9asWZg6dSrOnz+PvXv3VtuvdevWGDVqFL777jv06NEDSqUSS5cuBQBkZGRg9uzZaNmyJZydnREREYGlS5eivLzc6BxLly5F79694evrC09PT/Ts2RNr1qyBNa7xq+9S3LVrF5566in4+/vDz88P48ePR1pamtG+ZWVlePnllxEUFARXV1f0798fhw4dqvG8pnxWfdfgu+++izfeeAMRERFQKBTYtWtXjec8evQofv75Z8ycORP3339/jfv06tXLEKL//ve/QyKR1PqZr169athW2/fWo0cPDBgwoNo5NBoNQkNDMX78eMO20tJSvPHGG+jUqRMUCgVatGiB6dOn4+bNmzXWSmRNTrYugMheeHp64uGHH8batWsxe/ZsALqgI5VKMXHiRMTHxxvtX1JSgkGDBuHSpUtYunQpunXrhj179iAuLg7Hjx/Hli1bAOjG7IwbNw779+/H4sWL0atXL+zbtw/Dhw+vVkNSUhL69u2LVq1a4YMPPkBQUBC2b9+OuXPnIisrC0uWLKnXZ1uzZg0UCgUmTZqEnJwcxMXFYc2aNejfv3+1ff/8808kJyfjtddeQ0REBNzc3JCRkYG7774bUqkUixcvRtu2bXHgwAG88cYbuHr1KtatW2c4/urVq5g9e7bhR/rgwYN47rnnkJqaisWLF9er/juZNWsWRo4ciU2bNuH69et46aWX8Pjjj2Pnzp2GfZ544gls2LABCxYswAMPPIDTp09j/PjxyM/PNzqXOZ8VAP75z3+iQ4cOeP/99+Hp6Yn27dvXWOOOHTsAAOPGjbPsh69Q0/cWEhKC559/HhcuXDCqa8eOHUhLS8P06dMBAFqtFmPHjsWePXvw8ssvo2/fvrh27RqWLFmC++67D0eOHIGLi4tV6iaqkSCiBlm3bp0AIA4fPix27dolAIjTp08LIYTo1auXmDZtmhBCiM6dO4uBAwcajvvss88EAPHvf//b6HzvvPOOACB27NghhBDi559/FgDERx99ZLTfm2++KQCIJUuWGLYNHTpUtGzZUuTl5Rnt++yzzwqlUilycnKEEEJcuXJFABDr1q274+e7evWqkEql4pFHHjFsGzhwoHBzcxMqlcpo3/DwcCGTycS5c+eMts+ePVu4u7uLa9euGW1///33BQBx5syZGt9bo9GIsrIysWzZMuHn5ye0Wm2dtU6dOlW4ubnV+rqbm5uYOnWq4bn+u3v66aeN9nv33XcFAJGeni6EECI5OVkAEC+88ILRfhs3bhQAjM5p6mfVfwdt27YVpaWldX4uIYSYM2eOACDOnj17x32FEGLJkiWipv+L13/mK1euGLbV9r1lZWUJZ2dn8eqrrxptnzBhgggMDBRlZWVCCCG+/vprAUBs3rzZaL/Dhw8LAGLFihUm1UxkKeyWIrKggQMHom3btli7di1OnTqFw4cP19oltXPnTri5ueHhhx822q6fefPrr78CgKGbYtKkSUb7PfbYY0bPS0pK8Ouvv+LBBx+Eq6srysvLDbcRI0agpKQEBw8eNPszrVu3Dlqt1uhzzJgxA4WFhUhISKi2f7du3dChQwejbT/99BMGDRqEkJAQo7r0rU9VZ/ns3LkTQ4YMgZeXF2QyGeRyORYvXozs7GxkZmaaXb8pxowZU+0zAMC1a9cA1P4dTJgwAU5Oxg3g5nxW/XvL5XLLfZh6qul78/Pzw+jRo/Hll19Cq9UCAG7duoX//e9/mDJliuGz//TTT/D29sbo0aONPnP37t0RFBRU4yxCImtiuCGyIIlEgunTp+Nf//oXPvvsM3To0KHGMQsAkJ2djaCgoGrjIgICAuDk5ITs7GzDfk5OTvDz8zPaLygoqNr5ysvL8fHHH0MulxvdRowYAUA328YcWq0W69evR0hICKKjo5Gbm4vc3FwMGTIEbm5uNc4OCw4Orrbtxo0b+PHHH6vV1blzZ6O6Dh06hNjYWADAF198gX379uHw4cNYtGgRgDsPcnVycoJGo6n19fLy8hqDxO1/W4VCYfR++u/i9r95Td+LqZ9Vr6a/V0303XRXrlwxaX9z1VbHjBkzkJqaisTERAC6rla1Wm00/f3GjRvIzc2Fs7Nztc+dkZFh9n93RA3FMTdEFjZt2jQsXrwYn332Gd58881a9/Pz88Mff/wBIYRRwMnMzER5eTn8/f0N+5WXlyM7O9vohzQjI8PofD4+PpDJZJg8eTKeeeaZGt8zIiLCrM/yyy+/GFovbv8RB3TjYZKSkhAVFWXYVtMgVn9/f3Tr1q3Wv0dISAgA4JtvvoFcLsdPP/0EpVJpeP377783qd7AwECUlJQgJycHvr6+Rq9lZ2dDrVYjMDDQpHNVpf/sGRkZCA0NNWzXfy9VmfpZ9Wr6e9Vk6NChePXVV/H9999j2LBhd9xf//dTq9WGsAbUHnBrq2Po0KEICQnBunXrMHToUKxbtw69e/c2+s71A7G3bdtW4zma+zII1Pww3BBZWGhoKF566SWcPXsWU6dOrXW/wYMH49///je+//57PPjgg4bt+jVkBg8eDAAYNGgQ3n33XWzcuBFz58417Ldp0yaj87m6umLQoEE4duwYunXrBmdn5wZ/ljVr1kAqleK7776Dl5eX0Wt//fUXJk+ejLVr1+L999+v8zyjRo3C1q1b0bZt2zqnKkskEjg5OUEmkxm2FRcX46uvvjKp3iFDhuCtt95CQkICnnrqKaPX/v3vfxv2MZd+8cWNGzciOjra6Jy3z/Yy9bOaq2fPnhg+fDjWrFmDCRMm1Dhj6siRIwgICECrVq3QunVrAMDJkyfRq1cvwz4//vijWe+rD8zx8fHYs2cPjhw5gs8//9xon1GjRuGbb76BRqNB7969zf9wRBbGcENkBW+//fYd95kyZQo+/fRTTJ06FVevXkXXrl2xd+9evPXWWxgxYoThRzg2Nhb33nsvXn75ZRQWFiImJgb79u2r8Qf/o48+Qv/+/TFgwAA89dRTaN26NfLz83Hx4kX8+OOPRrN/7iQ7Oxv/+9//MHToUIwdO7bGfT788ENs2LABcXFxdY4bWbZsGRITE9G3b1/MnTsXHTt2RElJCa5evYqtW7fis88+Q8uWLTFy5EgsX74cjz32GJ588klkZ2fj/fffN2p5qMugQYMwZswYPP/887h69SoGDhwIIQR+//13fPjhhxgzZky9VomOjIzE448/jvj4eMjlcgwZMgSnT582zHCqz2etjw0bNmDYsGEYPnw4ZsyYgeHDh8PHxwfp6en48ccf8fXXX+Po0aNo1aoVRowYAV9fX8ycORPLli2Dk5MT1q9fj+vXr5v9vjNmzMA777yDxx57DC4uLpg4caLR64888gg2btyIESNG4Pnnn8fdd98NuVyOv/76C7t27cLYsWONAjyR1dl6RDNRc1d1tlRdbp8tJYQQ2dnZYs6cOSI4OFg4OTmJ8PBwsXDhQlFSUmK0X25urpgxY4bw9vYWrq6u4oEHHhBnz56tNltKCN0snBkzZojQ0FAhl8tFixYtRN++fcUbb7xhtA/uMFsqPj5eABDff/99rfvoZ3zpZ8mEh4eLkSNH1rjvzZs3xdy5c0VERISQy+XC19dXREdHi0WLFomCggLDfmvXrhUdO3YUCoVCtGnTRsTFxYk1a9ZUm+FTm9LSUvHWW2+Jzp07C4VCIRQKhejcubN46623qs1Kqu27089627Vrl2GbWq0WL774oggICBBKpVLcc8894sCBAyI8PNxotpSpn1X/Hbz33nt3/ExVFRcXi3/+85+iT58+wtPTUzg5OYmQkBAxfvx4sWXLFqN9Dx06JPr27Svc3NxEaGioWLJkiVi9enWNs6Vq+970+vbtKwCISZMm1fh6WVmZeP/998Vdd90llEqlcHd3F506dRKzZ88WFy5cMOszEjWURAgrrIxFREREZCOcLUVERER2heGGiIiI7ArDDREREdkVhhsiIiKyKww3REREZFcYboiIiMiuONwiflqtFmlpafDw8DB52XMiIiKyLSEE8vPzERISAqm07rYZhws3aWlpCAsLs3UZREREVA/Xr1+/4yrfDhdu9Bdwu379erVl04mIiKhpUqlUCAsLM+lCrA4XbvRdUZ6engw3REREzYwpQ0o4oJiIiIjsCsMNERER2RWGGyIiIrIrDjfmxlQajQZlZWW2LqPZksvlkMlkti6DiIgcEMPNbYQQyMjIQG5urq1Lafa8vb0RFBTE9YSIiKhRMdzcRh9sAgIC4Orqyh/mehBCoKioCJmZmQCA4OBgG1dERESOhOGmCo1GYwg2fn5+ti6nWXNxcQEAZGZmIiAggF1URETUaDiguAr9GBtXV1cbV2If9H9Hjl0iIqLGxHBTA3ZFWQb/jkREZAsMN0RERGRXGG6oVvfddx/mzZtn6zKIiIjMwgHFduBO3T9Tp07F+vXrzT7vd999B7lcXs+qiIiIbIPhxg6kp6cbHickJGDx4sU4d+6cYZt+5pJeWVmZSaHF19fXckUSEVGthBAoLNVAoxGV21Dlsaiybw3H1v5a1eNue7WWc4pqu9VcR/XjKp/JpBIEexn/9jQmhhs7EBQUZHjs5eUFiURi2Hb16lUEBwcjISEBK1aswMGDB7Fy5UqMGTMGzz77LPbs2YOcnBy0bdsWr776Kh599FHDue677z50794d8fHxAIDWrVvjySefxMWLF/Htt9/Cx8cHr732Gp588slG/bxERE1NSZkGqpIy5JeUQ1Wsu88vKa/YZrxdZdhejvySMqiKy1CgLof29mTSjAV4KHBo0RCbvT/DzR0IIVBcprHJe7vIZRabcfS3v/0NH3zwAdatWweFQoGSkhJER0fjb3/7Gzw9PbFlyxZMnjwZbdq0Qe/evWs9zwcffIB//OMfePXVV/Gf//wHTz31FO6991506tTJInUSETW2co3WKIzcMaSUVNlesU+pRmvrj1Grqj8jt/+iVP2NkRhtv20/1H6Smo5TyG07pJfh5g6KyzSIWrzdJu+dtGwoXJ0t8xXNmzcP48ePN9q2YMECw+PnnnsO27Ztw7fffltnuBkxYgSefvppALrA9OGHH+K3335juCEiswghIERlt4YQus4Pfc+GgKh8fNu2asdogcLS21tDKu5rDCO67fqwUlRqmX/ASiSAu8IJnko5PJS6e08XJ3hUee6hdIKni+7eQymH5233cpnktnPWHD7071fTfsRw4zBiYmKMnms0Grz99ttISEhAamoq1Go11Go13Nzc6jxPt27dDI/13V/6yywQUcMJIVCq0aKkTAt1mQbqci1KyjS65+W6+5Kq28s1UJdpUVJeuY/69n1qOY+6XGsYJyFQQ8CoeA5DuKg9hBh6VEQdIaSJd7u4yGW1hw8X49DiUWW7Pry4OztBKmXIaAoYbu7ARS5D0rKhNntvS7k9tHzwwQf48MMPER8fj65du8LNzQ3z5s1DaWlpnee5fSCyRCKBVtt0m2OJLKVMo4WquAy5xboxEiUVgcKkAGIUKKqGker76AKHrT9t8yOXSaq3kNQSQjwrQkvVEOOhdIJcxtVR7AXDzR1IJBKLdQ01JXv27MHYsWPx+OOPAwC0Wi0uXLiAyMhIG1dGZD36GSm5RaXILSozhJW84jLkFpUht7hUt62ocltexesF6vJGr1ciAZROMijkUiidZFDKpVDo7+UyKJykUFa5r/q64Ti5zPBYcfs5nGSQSivHU0gkuq4PXQ/H7dsqnhu2SW7rFql7H/0pq79X5WgO/TH6DXXtc/t7O8uk7JohA/v71SaTtGvXDps3b8b+/fvh4+OD5cuXIyMjg+GGmoXScm1F6CitDCb6QFLRspJbVGoILnlVQkp5A6ek6P/l7+Jcd6jQPa9lnzqCiaLK6/zBJqofhhsH9frrr+PKlSsYOnQoXF1d8eSTT2LcuHHIy8uzdWnkIIQQyFeXI88omFSGFVWV1hSjbcVlDR4A6iyTwstVDm8XObxd5fBykcPLxRleFc8rt8krtule81Q6wYldF0RNnkQIx+rdValU8PLyQl5eHjw9PY1eKykpwZUrVxAREQGlUmmjCu0H/56OqVyjxY18NdJzi5GWV4L03GKk55UgLbcYN/LVyCsqNbSiNKQRRSIBPJVyQyCpDCIV9xVhRR9idPe6bUo5W0SImpu6fr9vx5YbIjKZViuQVaA2hBaj8JJXjPTcEmTml5gVWpRyqVEQ0QWTKoGlotXE+7bg4qHkzBQiqhnDDREB0HUT5RaVIS2vGGm5JUivcp+eqwsvN1QlKNPcObnIZRIEeioR4uWCYG8lQrxdEOKlRKCnEj5ulWHF00UOpQVnBRIRAQw3RA4jv6TM0D2UXrXlpUp4KSm787R+qQQI8FDqQouXC4K9lAiuCC/6e393BVtViMhmGG6I7EBJmcYQWgzh5baWl3wTpzL7uTkjxFsXWvT3VcNLgIeC64E0N0IAahVQfEt3K8rR3Zfk6Zb3NQy9vG1J4Dqfm7NvXc9hwv53OJdEAvi2AUJ6AP4dAClbAx0dww1RE6fVCqTmFleGl4qwUjW83CoqhRM0cIIGcmjghHI4QQNnlMNJokEANAiVaOCtEAh2d0KAmxQBbjK0cJXA30UKXxcp/JQSeCkAZ4kG0JQB2nJAU6p7nFsOZJfpnmvLK16veK4pr3hcVmX7bcfrj4EAFB6AwhNQegJKr4rH3rc9r/rYS3cMf7BqDyk13W5/TdjmGnmNTu4KBN8FBHfXhZ2QHoBfO0DKQO5IGG6ImqACdTn2J19H+p8/ocX1HWiruYwAlCFUojGEGOeKAOOEcjgrzfjhKqi4NTfOHrqgc3vwUXoaP1Z6AYoa9pO7VL8aoK3UGVJygeIc64QUJxfA1Rdw8dHdlF6AtOJnwPC3kZjx3NR9cYfX63huyr6aUiDzLJB+AigrBFIO6G56zh5AcLfKsBPSA/CJYOCxYww3RE3E9Zwi/H7qEnJPbEGbrJ0YKDkOV4la92J9/j9YIgNkckAq190bHjsBMufKx1K57rnhsdz4uHod76z70bz9eABQ5wMlKl2XiDpPd1+i0v3Y6x+X5FU+Ly/RHVear7up6vkHljrV0jLkXUtAqhqeKu5lxpcfqRZSjMJIrnFIuT2oNDSkuPhUCSregEuV0FI1wLj4VLzmrQt49kyrAbIvAmnHKm/pJ3X/3Vzbp7vpKbxqCDytm04ApgZhuCGykXKNFn+m5GL/qfMoT9qC7oV78LD0FBSSckOYyXUOQmGbkQjoMQxyF0/Tw4VUbj//Ki1X3xZ+8moPQob9co1fE1pd11hRtu5WX3LXylagEpXlQoohkHjfFkhqCSv2HlLqSyoDWnTU3e56RLdNUw5kna8Sdo4DGad0wfrqHt1NT+kNhHSvDDvB3QHvVgw8zRDDDVEjyisqw2/nM3H4dDKUF7dhoOYAnpUmwUmiBSqGlOS6toa202j4RD8E75Du8Hb0/2N1UgDuLXS3+hACKC24LQjV0HJUY0iqeFxWqDtXWZHudjuZoiKAVGlJMQoktQQVhhTrkzkBgVG6W49Jum2aMuDm2YrAc1x3f+O0LhRf/k1303PxNW7dCekOeIYy8DRxDDcEALjvvvvQvXt3xMfH27oUuyKEwKWbhdh59gZOnDqFoPRfMFR6CMsk5yGVCEOgyfPqBEXXcVB2GwfvFp34f5yWJJFUDGL2ALxC63cOTVlFd1puRdgp0nVb6cMKQ0rzIpMDQV11t55TdNvKS4HMpMrWnbRjwI0zuq7FS7/qbnpuLYxbd0J6AJ7BtvgkVAuGGzswevRoFBcX45dffqn22oEDB9C3b18cPXoUPXv2tEF1jqe0XItDV3Lw69kbOJd0HHepfscw2SE8Kb1s9L+4Av/ucLlrHGRRY+Dl19Z2BdOdyeS6EOPqa+tKyFqcnCu6pLpXbisrATLPVLbupB3XBaDCm8CFHbqbnntQZcuOPvi4BzTqR7AarVY3bslo0HvF45Lc27bl6rYpvYDpW21WMsONHZg5cybGjx+Pa9euITw83Oi1tWvXonv37gw2VpZVoMaus5nYmXwDGRePYaBmPyZKD6OT9DpQMQZVQAJ1SG8ouz0IRI6Cu1dL2xZNRHWTK4HQaN1Nr6xY16JTddDyzbNAQQZw/mfdTc8z1HhKekh3wM2/sT9FpXK1CeGk6rYqYUXceYFPIy62/YcAw40dGDVqFAICArB+/XosWbLEsL2oqAgJCQl48cUX8eijj2LPnj3IyclB27Zt8eqrr+LRRx+1YdXNmxACSekq7EzOxK/JNyDS/sQw6SG8LD2ECOkNw/+ytBInaFvfC6fOYyDpNBJKe/mXHJGjkrsALWN0N73SQiDjtPGg5ZvnAFWq7nZuS+W+XmHVBy2b0yKo1RrP0Ks1nNy2vSS35vFi5jAMgPeuspyAd5Xn3pXbbNzKyXBzJ0I0/D+I+pK7mjT2wsnJCVOmTMH69euxePFiw9WOv/32W5SWlmLWrFn4+uuv8be//Q2enp7YsmULJk+ejDZt2qB3797W/hR2o7hUg/2XsvDr2UzsTk5HSP4pDJcdwqeywwh1rpyBo5UpIGl7PyRRYyHtOAxSFx8bVk1EVufsBrTqrbvpqQuAjJPGg5azLwB513W35B8r9/UOrwg6d+lmPtbVmqJfVbreJMYhxDDo3fu2wOJTPbDIlQ1438YlEcKwnrVNrFixAu+99x7S09PRuXNnxMfHY8CAAbXu/+mnn+KTTz7B1atX0apVKyxatAhTpkwx+f3qumR6SUkJrly5goiICCiVFV9iaSHwVki9PluDvZqm+x+NCc6ePYvIyEjs3LkTgwYNAgAMHDgQoaGh2LRpU7X9R44cicjISLz//vsArDOguMa/ZzOTlluMnWczsfNsJv64mIEe2jMYLj2EWNkRtJDkGfbTyl0h7TAUiBwDtI8FFO42rJqImqSSPN26O/oBy2nHgJzL9TuX3LVKCKlyf6fAovBststE1PX7fTubttwkJCRg3rx5WLFiBfr164fPP/8cw4cPR1JSElq1alVt/5UrV2LhwoX44osv0KtXLxw6dAhPPPEEfHx8MHr0aBt8gqajU6dO6Nu3L9auXYtBgwbh0qVL2LNnD3bs2AGNRoO3334bCQkJSE1NhVqthlqthpubacHJkWi1Aif+ysXOs5n4JTkTl9Oz0F96CiNkh7FcdhTeToWGfYXSC5KOI4DIMZC2HcQZM0RUN6UXEDFAd9MrvqVbWTntuK6lB5I7t6Q0s1YUW7BpuFm+fDlmzpyJWbNmAQDi4+Oxfft2rFy5EnFxcdX2/+qrrzB79mxMnDgRANCmTRscPHgQ77zzjvXCjdxV14JiC3JXs3afOXMmnn32WXz66adYt24dwsPDMXjwYLz33nv48MMPER8fj65du8LNzQ3z5s1DaWmplQpvXvJLyrD3gq67adfZTBQXqnCf9Diekh3G/YpjcJeUGPYVbi0g6TQSiBwDSesBuhkWRET15eIDtLlPdyOLsVm4KS0txdGjR/HKK68YbY+NjcX+/ftrPEatVlfr3nBxccGhQ4dQVlYGuVxe43ENIpGY3DVkaxMmTMDzzz+PTZs24csvv8QTTzwBiUSCPXv2YOzYsXj88ccBAFqtFhcuXEBkZKSNK7ada9mF+DW5orvpSjZcNAUYLP0Tb8kOY6DyBJQoq9zZMxSIHK0LNK3u4QUciYiaOJuFm6ysLGg0GgQGBhptDwwMREZGRo3HDB06FKtXr8a4cePQs2dPHD16FGvXrkVZWRmysrIQHFx9ESV9F4yeSlXfC9M0fe7u7pg4cSJeffVV5OXlYdq0aQCAdu3aYfPmzdi/fz98fHywfPlyZGRkOFS4KdNocfTaLew8q5vddOlmIXyhQqzsCGZJD6Of/AzkKK88wCcCiBqjG0MT0rPZ9lETETkim8+Wktw2G0gIUW2b3uuvv46MjAzcc889EEIgMDAQ06ZNw7vvvguZrOZ/TcfFxWHp0qUWr7upmjlzJtasWYPY2FjDuKXXX38dV65cwdChQ+Hq6oonn3wS48aNQ15e3h3O1rwVqMvxS9IN3eymc5lQlZQjEDkYJjuMN50P427pWUhRZdZBi8iKQDMaCOzCVYKJiJopm4Ubf39/yGSyaq00mZmZ1Vpz9FxcXLB27Vp8/vnnuHHjBoKDg7Fq1Sp4eHjA37/mhZEWLlyI+fPnG56rVCqEhYVZ7oM0MX369MHtE+B8fX3x/fff13ncb7/9Zr2ibOBadiEmrf4Df90qRpjkBiZKD2O08gi64bzxjsHdK1to/NvbpFYiIrIsm4UbZ2dnREdHIzExEQ8++KBhe2JiIsaOHVvnsXK5HC1b6lZ3/eabbzBq1ChIa+k2UCgUUCgUliucmrwLN/Ix/4ufMKZ4F8a5HEIHcaXKqxIgrLcu0HQaBfiE13oeIiJqnmzaLTV//nxMnjwZMTEx6NOnD1atWoWUlBTMmTMHgK7VJTU1FRs2bAAAnD9/HocOHULv3r1x69YtLF++HKdPn8aXX35py49BTYU6H6n7E5C7ex3+J85AKheAACCRAa37VwwKHg14BNm6UiIisiKbhpuJEyciOzsby5YtQ3p6Orp06YKtW7caro+Unp6OlJQUw/4ajQYffPABzp07B7lcjkGDBmH//v1o3bq1jT4B2ZymHLj8G3Dia2iTf0KopgShACABysL6Qd7jEaDjSMDNz8aFEhFRY7H5CsWNzewViqnerPb3FALIOAWc+AY49S1QmGl46aI2BIc8H8DoyfPgEdjGcu9JREQ21WxWKG6qHCzvWY3F/46qNF2YOfENkJlk2Fyq8ME3xb3xn7J+8GxzN1ZNjYGrM//TJiJyVPwFqEK/CGBRURFcXLiUfkMVFekuONqgxRXVBcDZn3SB5vJv0A2iASBTAB2H46j3UDy+2x3FGhkGdwrAp5N6QinnIntERI6M4aYKmUwGb29vZGbqujlcXV1rXXOHaieEQFFRETIzM+Ht7V3rGkS10mqAK7uBEwm6K+eWVV7PCa36AHc9AkSNw/dnC/Hityeg0QqM7BaM+IndIZdxsT0iIkfHcHOboCDdTBp9wKH68/b2Nvw9TXLjTOU4mvz0yu2+bYC7HgW6TQB8WgMAvj6Uglf/ewpCAA9Ht8Q7D3WDTMogSkREDDfVSCQSBAcHIyAgAGVlZXc+gGokl8tNa7HJv6ELMye/0Q0S1nPxATqP14WaljFGqwWv2XsF//hJN+Zm8j3hWDqmM6QMNkREVIHhphYymcz87hQyTWkRcG4rcOJr4NJOQFRcAkEqBzoM1QWa9rE1XnH7k50X8P4O3SrDs+9tg1eGd2LXIRERGWG4ocah1QLX9uq6nZJ+AErzK19reTdw10RdS42rb42HCyHw3vZzWPHbJQDAvCHt8fzg9gw2RERUDcMNWdfNc7pAc/LfgOqvyu3e4bqBwd0mAn5t6zyFEAJLf0zC+v1XAQCvjuiEJ++t+xgiInJcDDdkeQU3gdObdd1O6ccrtyu8gC4PAt0eAVrdY9JVtzVagUX/PYVvDl8HAPxjXBdMvofXgyIiotox3JBllJXoxtGcTAAuJAJCo9sudQLaPaBrpekwDJCbvlJxmUaLBd+ewP+Op0EqAd59+C48HN3SSh+AiIjsBcMN1Z9WC6Qc0M10OvM/QJ1X+VpIT93A4C7jATd/s0+tLtfguU3HsCPpBpykEnz0SA+M7BZsweKJiMheMdyQ+bIu6gLNyQQgt/LCpvAK061F0+0RoEWHep++uFSD2f86it/P34SzkxQrJ/XE4MhACxRORESOgOGGTFOUUzGO5hsg9UjldmcPoPNYXaAJ7wdIG7ZCcIG6HDPWH8ahKzlwkcuwemoM+rUzv+WHiIgcF8MN1a5cDZzfrgs0F3YA2opFDSUyoN1g3UynjiMAZ1eLvF1eURmmrDuEE9dz4aFwwrrpvRDTuuap4URERLVhuKHqsi4AB1cAp78DSnIrtwd1042j6fow4B5g2bcsUGPymkNITlfB21WOr2b0RteWXhZ9DyIicgwMN2SsrBhYNxwovKl77hECdPs/XbdTYJRV3jIjrwSTVh/EpZuF8HdXYOOs3ugY5GGV9yIiIvvHcEPGLu3SBRv3IGD850DrAYDUepehuJ5ThEmr/0BKThGCvZTYOKs32rRwt9r7ERGR/WO4IWPJP+ruOz8ItLnPqm91+WYBJq3+A+l5JWjl64qNs3ojzNcy43eIiMhxMdxQJU2ZbiE+AIgcbdW3OpuhwuOrDyGrQI12Ae7YOKs3Aj1NX+CPiIioNgw3VOnqXt0AYld/3eURrOTkX7mYsvYQcovKEBXsia9m3g0/d4XV3o+IiBwLww1V0ndJdRpptXE2h6/mYPq6wyhQl6N7mDe+nH43vFzlVnkvIiJyTAw3pKPVAmd/0j2OHGOVt9h7IQtPbDiC4jINekf4Ys20XnBX8D9BIiKyLP6ykM5fh4GCG4DCE4i41+Kn/yXpBp7e9CdKy7UY2KEFPns8Gi7O1puFRUREjovhhnTOVnRJdRgKODlb9NQ/nUzDvG+Oo1wrMLRzIP75aA8onBhsiIjIOhhuCBCicryNhWdJfXvkOv62+SS0AhjXPQTv/99dcJI17PpTREREdWG4IeDGaeDWVcBJCbQbYrHTfnXgKl7/3xkAwCO9wvDmg10hk0osdn4iIqKaMNxQZatNuyGAs5tFTvn57kuI+/ksAGB6v9ZYPCoKEgmDDRERWR/DDVm0S0oIgfhfLuCjXy8AAJ4Z1BYLYjsy2BARUaNhuHF0WReBzCRA6qQbTNwAQgjE/XwWq36/DAB4aWhHPDOonSWqJCIiMhnDjaPTz5KKuBdw8an3abRagcU/nMa/DqYAABaPisKM/hGWqJCIiMgsDDeOzgJdUuUaLV7efBLf/ZkKiQSIe7ArHrm7lYUKJCIiMg/DjSPLSwVSjwKQAB1H1usUpeVavJBwHFtOpUMmlWD5hLswtnuoZeskIiIyA8ONIzu7RXcf1hvwCDT78JIyDZ7e+Cd2ns2Es0yKjx/rgaGdgyxcJBERkXkYbhxZ8g+6+3p0SRWqy/HEhiPYfykbCicpVk2JwcAOLSxcIBERkfkYbhxVYTZwbZ/uceQosw5VlZRh+rrDOHrtFtycZVgzrRfuaeNnhSKJiIjMx3DjqM5tBYQWCOoG+LQ2+bCcwlJMWfsHTqeq4Kl0wpcz7kaPVvWfZUVERGRpDDeOyjBLaozJh2Tml+Dx1X/g/I0C+Lo546uZd6NziJeVCiQiIqofhhtHVKICLu/SPTZxvE1abjEmrf4DV7IKEeChwKYneqNdgIcViyQiIqofhhtHdDER0JQCfu2BFh3vuPu17EI89sUfSM0tRqi3CzY90Rvhfpa5BhUREZGlMdw4IkOX1CjgDtd8unAjH5NW/4HMfDUi/N2wcVZvhHi7NEKRRERE9cNw42jKSoDzO3SP79AldSYtD5PXHEJOYSk6Bnrgq1l3I8BD2QhFEhER1R/DjaO5vAsoKwQ8Q4GQnrXu9mfKLUxbewiqknJ0DfXChhl3w8fNuRELJSIiqh+GG0dT9VpStXRJHbycjZnrD6OwVIOYcB+snd4Lnkp5IxZJRERUfww3jkRTplvfBqi1S6pco8UzG/9EYakG/dv5Y9WUaLg68z8TIiJqPvir5Uiu7QOKbwGu/kCrPjXucjmrENmFpXBzlmH11Bgo5bJGLpKIiKhhpLYugBqRvkuq0whAWnNoOZOWBwCICvFksCEiomaJ4cZRaLWVVwGvY1Xi06kqAODKw0RE1Gwx3DiK1KNAfjrg7AFE3FvrbvqWm84hno1VGRERkUUx3DiK5B909x2GAk6KGncRQuBMGltuiIioebN5uFmxYgUiIiKgVCoRHR2NPXv21Ln/xo0bcdddd8HV1RXBwcGYPn06srOzG6naZkoI4yngtbieU4z8knI4y6RoH+jeSMURERFZlk3DTUJCAubNm4dFixbh2LFjGDBgAIYPH46UlJQa99+7dy+mTJmCmTNn4syZM/j2229x+PBhzJo1q5Erb2ZunAFuXQGclEC7IbXudrqiS6pjkAfkMpvnXiIionqx6S/Y8uXLMXPmTMyaNQuRkZGIj49HWFgYVq5cWeP+Bw8eROvWrTF37lxERESgf//+mD17No4cOdLIlTcz+labtoMBRe0tMvrxNl1COd6GiIiaL5uFm9LSUhw9ehSxsbFG22NjY7F///4aj+nbty/++usvbN26FUII3LhxA//5z38wcuTIWt9HrVZDpVIZ3RyOCV1SQOVMqSiOtyEiombMZuEmKysLGo0GgYGBRtsDAwORkZFR4zF9+/bFxo0bMXHiRDg7OyMoKAje3t74+OOPa32fuLg4eHl5GW5hYWEW/RxNXvYlIPMMIHXSDSaug34wcRfOlCIiombM5gMrJLdd30gIUW2bXlJSEubOnYvFixfj6NGj2LZtG65cuYI5c+bUev6FCxciLy/PcLt+/bpF62/yzv6ku289AHD1rXW3TFUJsgrUkEqATkEMN0RE1HzZ7PIL/v7+kMlk1VppMjMzq7Xm6MXFxaFfv3546aWXAADdunWDm5sbBgwYgDfeeAPBwcHVjlEoFFAoap767BAMXVKj6txNP5i4XYA7XJy5MjERETVfNmu5cXZ2RnR0NBITE422JyYmom/fvjUeU1RUBKnUuGSZTPdDLISwTqHNmSoN+OswAAnQqe5wc4YrExMRkZ2wabfU/PnzsXr1aqxduxbJycl44YUXkJKSYuhmWrhwIaZMmWLYf/To0fjuu++wcuVKXL58Gfv27cPcuXNx9913IyQkxFYfo+nSX24h7G7AI6jOXU9zZWIiIrITNr0q+MSJE5GdnY1ly5YhPT0dXbp0wdatWxEeHg4ASE9PN1rzZtq0acjPz8cnn3yCF198Ed7e3rj//vvxzjvv2OojNG36VYnvMEsKAFcmJiIiuyERDtafo1Kp4OXlhby8PHh62nErRWE28H57QGiAuccB34had80tKkX3ZbruwRNLYuHlIm+kIomIiExjzu+3zWdLkZWc/1kXbIK61hlsACCpotWmla8rgw0RETV7DDf2yjBLaswddz3NlYmJiMiOMNzYI3U+cGmX7jHH2xARkYNhuLFHFxIBjRrwbQu06HTH3U+n6lpuojhTioiI7ADDjT2qei2pWlZ71isqLcflrEIAQBe23BARkR1guLE3ZSXAhR26xyaMt0lOV0EIIMBDgRYeDrySMxER2Q2GG3tz+TegtADwDAVCetxxd8PFMkPZakNERPaB4cbe6LukOo0CpHf+evXjbbgyMRER2QuGG3uiKQfOVVxywYRZUgBnShERkf1huLEn1/YBxbcAVz+gVZ877l5arsX5G/kA2HJDRET2g+HGnpz9SXffcTggu/Nlw87fyEeZRsDLRY6WPi5WLo6IiKhxMNzYC60WSK4INybMkgKAM1WuBC65w5RxIiKi5oLhxl6k/QnkpwHOHkDEQJMO4UwpIiKyRww39iL5B919h1hArjTpEM6UIiIie1TvcHPx4kVs374dxcXFAAAhhMWKIjMJYbwqsQk0WoHkdP1gYrbcEBGR/TA73GRnZ2PIkCHo0KEDRowYgfT0dADArFmz8OKLL1q8QDJBZhKQcxmQKYB2D5h0yJWsAhSXaeAilyHC383KBRIRETUes8PNCy+8ACcnJ6SkpMDV1dWwfeLEidi2bZtFiyMT6Vtt2g0GFO4mHaIfbxMV4gmZlIOJiYjIftx5vvBtduzYge3bt6Nly5ZG29u3b49r165ZrDAyg5ldUgDH2xARkf0yu+WmsLDQqMVGLysrCwoFL7zY6HIuAzdOAxIZ0GGYyYcZZkpxvA0REdkZs8PNvffeiw0bNhieSyQSaLVavPfeexg0aJBFiyMT6Ne2ad0fcPU16RAhhKHlJootN0REZGfM7pZ67733cN999+HIkSMoLS3Fyy+/jDNnziAnJwf79u2zRo1Ul3p0Sf11qxiqknLIZRJ0CPSwUmFERES2YXbLTVRUFE6ePIm7774bDzzwAAoLCzF+/HgcO3YMbdu2tUaNVBtVOvDXId3jTqNMPky/MnGHQA84O3GpIyIisi9mt9wAQFBQEJYuXWrpWshc+mtJtbwb8Aw2+TCOtyEiIntm9j/bIyIi8Prrr+PcuXPWqIfMUY8uKaAy3HQO5XgbIiKyP2aHm+eeew7btm1DZGQkoqOjER8fb1jIjxpRUQ5wda/ucaTpXVJA1WngbLkhIiL7Y3a4mT9/Pg4fPoyzZ89i1KhRWLlyJVq1aoXY2FijWVRkZee3AUIDBHYFfNuYfFhmfgky89WQSIDIYA4mJiIi+1Pv0aQdOnTA0qVLce7cOezZswc3b97E9OnTLVkb1cXQJWVeq42+S6qNvxtcnes15IqIiKhJa9Cv26FDh7Bp0yYkJCQgLy8PDz/8sKXqorqoC4CLv+oemzneJkk/mDiUXVJERGSfzA4358+fx8aNG7Fp0yZcvXoVgwYNwttvv43x48fDw4PdHI3iYiKgUeu6owKizDqUl10gIiJ7Z3a46dSpE2JiYvDMM8/gkUceQVBQkDXqorpUnSUlMe+il5wGTkRE9s6scKPRaPDZZ5/h4Ycfhq+vaUv9k4WVlQDnt+seR44x69C84jKk5BQB4GUXiIjIfpk1oFgmk2Hu3LnIy8uzVj10J1d2A6UFgEcIENLTrEP1421a+rjA29XZGtURERHZnNmzpbp27YrLly9boxYyRfIPuvvIUYDUvK9Pf9kFjrchIiJ7Zna4efPNN7FgwQL89NNPSE9Ph0qlMrqRFWnKgXM/6x6bOUsK4HgbIiJyDGYPKB42bBgAYMyYMZBUGcwqhIBEIoFGo7FcdWQs5QBQlA24+AKt+pp9uGGmFC+7QEREdszscLNr1y5r1EGm0M+S6jgCkJn31RWXanDpZgEAttwQEZF9MzvcDBw40Bp10J1otfW+UCYAJGeooBWAv7sCAZ5KCxdHRETUdJgdbn7//fc6X7/33nvrXQzVIe0YkJ8GOLsDbe4z+3DDeBt2SRERkZ0zO9zcd9991bZVHXvDMTdWop8l1T4WkJvf8nKGKxMTEZGDMHu21K1bt4xumZmZ2LZtG3r16oUdO3ZYo0YSosoUcPO7pADOlCIiIsdhdsuNl1f1H8cHHngACoUCL7zwAo4ePWqRwqiKzGQg5zIgUwDtHzD78DKNFucy8gEAnRluiIjIzpndclObFi1a4Ny5c5Y6HVV19ifdfdv7AYX5Fye9cKMApRotPJROCPN1sXBxRERETYvZLTcnT540ei6EQHp6Ot5++23cddddFiuMqqi6KnE9nK6yMrHEzAttEhERNTdmh5vu3btDIpFACGG0/Z577sHatWstVhhVyLkCZJwCJDKgw/B6nSKJ422IiMiBmB1urly5YvRcKpWiRYsWUCq5dopV6LukWvcD3PzqdQquTExERI7E7HATHh5ujTqoNoaF+8bU63CtViApnS03RETkOEweULxz505ERUXVeHHMvLw8dO7cGXv27LFocQ4vPwO4/ofucaeR9TrFlexCFJVqoJRL0aaFuwWLIyIiappMDjfx8fF44okn4OlZvWvDy8sLs2fPxvLlyy1anMPTd0m17AV4htTrFPr1bSKDPSGTcjAxERHZP5PDzYkTJwxXBK9JbGxsvda4WbFiBSIiIqBUKhEdHV1n68+0adMgkUiq3Tp37mz2+zYLDbiWlB5XJiYiIkdjcri5ceMG5HJ5ra87OTnh5s2bZr15QkIC5s2bh0WLFuHYsWMYMGAAhg8fjpSUlBr3/+ijj5Cenm64Xb9+Hb6+vvi///s/s963WSjKAa7u1T3uVL8p4EBlyw0X7yMiIkdhcrgJDQ3FqVOnan395MmTCA4ONuvNly9fjpkzZ2LWrFmIjIxEfHw8wsLCsHLlyhr39/LyQlBQkOF25MgR3Lp1C9OnTzfrfZuF89sBbTkQ0Bnwa1uvUwghcKZijRsOJiYiIkdhcrgZMWIEFi9ejJKSkmqvFRcXY8mSJRg1yvQWhtLSUhw9ehSxsbFG22NjY7F//36TzrFmzRoMGTLEPmdwWaBLKi2vBLeKyuAklaBDEAcTExGRYzB5Kvhrr72G7777Dh06dMCzzz6Ljh07QiKRIDk5GZ9++ik0Gg0WLVpk8htnZWVBo9EgMDDQaHtgYCAyMjLueHx6ejp+/vlnbNq0qc791Go11Gq14XlNs72aHHUBcOlX3WMLjLdpH+gBhZPMEpURERE1eSaHm8DAQOzfvx9PPfUUFi5caFihWCKRYOjQoVixYkW1oGKK2y8HIIQw6RIB69evh7e3N8aNG1fnfnFxcVi6dKnZddnUxV+A8hLAJwIIrP9g6dOG8TYcTExERI7DrEX8wsPDsXXrVty6dQsXL16EEALt27eHj4+P2W/s7+8PmUxWrZUmMzPzjiFJCIG1a9di8uTJcHZ2rnPfhQsXYv78+YbnKpUKYWFhZtfbqKp2STXgWlBJhvE2DDdEROQ4zF6hGAB8fHzQq1evBr2xs7MzoqOjkZiYiAcffNCwPTExEWPHjq3z2N27d+PixYuYOXPmHd9HoVBAoVA0qNZGVa7WDSYG6r0qsd7p1IqWm1AOJiYiIsdRr3BjKfPnz8fkyZMRExODPn36YNWqVUhJScGcOXMA6FpdUlNTsWHDBqPj1qxZg969e6NLly62KNu6Lu8GSvMBj2AgNLrep8kqUCNDVQKJRLeAHxERkaOwabiZOHEisrOzsWzZMqSnp6NLly7YunWrYfZTenp6tTVv8vLysHnzZnz00Ue2KNn6zlZ0SXUaCUhNnsxWjX59mwg/N7grbPo1ExERNSqb/+o9/fTTePrpp2t8bf369dW2eXl5oaioyMpV2YhWA5zdonvcgFlSAAzr27BLioiIHI1ZTQNlZWWYPn06Ll++bK16HFvKAaAoG3DxAcL7NehUZ1I5U4qIiByTWeFGLpfjv//9r7VqIf0sqY4jAFntl7owBVcmJiIiR2X2oI4HH3wQ33//vRVKcXBCWGRVYgBQlZTharau644tN0RE5GjMHnPTrl07/OMf/8D+/fsRHR0NNzc3o9fnzp1rseIcStqfgCoVkLsBbQY16FTJFYOJQ71d4ONW9zpARERE9sbscLN69Wp4e3vj6NGjOHr0qNFrEomE4aa+9K02HWIBubJBp9KvTBzFVhsiInJAZoebK1euWKMOx2bBLimA422IiMix1XshldLSUpw7dw7l5eWWrMcx3TwHZF8EZM5AuwcafDrOlCIiIkdmdrgpKirCzJkz4erqis6dOxsW2Zs7dy7efvttixfoEPStNm0GAcqGBZKSMg0u3iwAAHThGjdEROSAzA43CxcuxIkTJ/Dbb79BqawcGzJkyBAkJCRYtDiHkfyD7t4CXVJnM/Kh0Qr4uTkj0LMZXVOLiIjIQswec/P9998jISEB99xzDyRVrlgdFRWFS5cuWbQ4h3DrKpBxEpBIdevbNFDVlYklDbiiOBERUXNldsvNzZs3ERAQUG17YWEhf0zrI/kn3X14P8DNr8GnO83xNkRE5ODMDje9evXCli1bDM/1geaLL75Anz59LFeZozDMkhpjkdMlcaYUERE5OLO7peLi4jBs2DAkJSWhvLwcH330Ec6cOYMDBw5g9+7d1qjRfuXfAK7/oXvcaWSDT1em0SI5Ix8AW26IiMhxmd1y07dvX+zbtw9FRUVo27YtduzYgcDAQBw4cADR0dHWqNF+ndsCQAChMYBXaINPd+lmAUrLtfBQOKGVr2vD6yMiImqGzG65AYCuXbviyy+/tHQtjsfQJTXKIqfTj7eJDPGEVMrxT0RE5JhMCjcqlcrkE3p6sjvEJMW3gCu/6x53avgUcKDKTCl2SRERkQMzKdx4e3ubPBNKo9E0qCCHcX47oC0HAqIA/3YWOaV+ZWIOJiYiIkdmUrjZtWuX4fHVq1fxyiuvYNq0aYbZUQcOHMCXX36JuLg461Rpjyx4LSkA0GoFktIrpoGHsuWGiIgcl0nhZuDAgYbHy5Ytw/Lly/Hoo48ato0ZMwZdu3bFqlWrMHXqVMtXaW9KC4GLv+geWyjcXMspQoG6HAonKdq1cLfIOYmIiJojs2dLHThwADExMdW2x8TE4NChQxYpyu5d/AUoLwF8WgOBXSxySv14m05BHnCS1ft6qERERM2e2b+CYWFh+Oyzz6pt//zzzxEWFmaRouxe1S4pC63qfCZN3yXF8TZEROTYzJ4K/uGHH+Khhx7C9u3bcc899wAADh48iEuXLmHz5s0WL9DulJfqBhMDFluVGABOp3KmFBEREVCPlpsRI0bgwoULGDNmDHJycpCdnY2xY8fi/PnzGDGi4Rd+tHtXfgfUKsA9SLd4nwUIIZCUxplSREREQD0X8WvZsiXeeustS9fiGJJ/0N13GglILTM2JkNVguzCUsikEnQM8rDIOYmIiJqreoWb3NxcHDp0CJmZmdBqtUavTZkyxSKF2SWtBjhbcdFRC82SAirXt2kf4A6lXGax8xIRETVHZoebH3/8EZMmTUJhYSE8PDyMFveTSCQMN3VJOQgUZQFKb6B1f4ud9nTFTKkojrchIiIyf8zNiy++iBkzZiA/Px+5ubm4deuW4ZaTk2ONGu2HfpZUxxGATG6x057heBsiIiIDs8NNamoq5s6dC1dXXnXaLEJYfFVivTOcKUVERGRgdrgZOnQojhw5Yo1a7FvaMUD1FyB3A9oOsthpcwpLkZZXAoDdUkREREA9xtyMHDkSL730EpKSktC1a1fI5cbdK2PGWG7tFrty9ifdffshgNzFYqfVr0zc2s8VHkrLdXURERE1V2aHmyeeeAKA7hpTt5NIJLwqeG0MXVKWDX9cmZiIiMiY2eHm9qnfZIKb54Cs84DMGWgfa9FTc2ViIiIiY7zCYmPQL9zX5j5AadkQwpWJiYiIjJncclNTNxQAeHl5oWPHjoiNjYXUQivu2h0rzZIqUJfjclYhALbcEBER6Zkcbv773//WuD03Nxepqano3Lkztm/fjoCAAIsVZxduXQPSTwASqW59GwtKTte12gR7KeHnrrDouYmIiJork8PNsWPHan0tPT0djz32GF599VWsXr3aIoXZDf0sqfB+gJu/RU/N8TZERETVWaQfKTg4GG+88QZ27txpidPZFyt1SQFVZkpxvA0REZGBxQbJhIaGIjMz01Knsw8FmbrrSQG6q4BbGFtuiIiIqrNYuDlx4gRat25tqdPZh7NbAAggpCfg1dKipy4p0+BiZgEArnFDRERUlcljblQqVY3b8/LycPjwYbz44ouYNWuWxQqzC1bskjp/Ix/lWgEfVzlCvJQWPz8REVFzZXK48fb2hkQiqfE1iUSC2bNn4+WXX7ZYYc1ecS5wZbfusYVXJQaMx9vU9r0QERE5IpPDza5du2rc7unpifbt28Pd3d1iRdmF89sBbTnQIhLwb2fx0xvG24RyvA0REVFVJoebgQMHWrMO+6NfldgKXVIAZ0oRERHVhksKW0NpIXDxV91jK4Sbco3WsIBfF86UIiIiMsJwYw0XfwXKiwHvcCCoq8VPfzmrEOpyLdycZWjt52bx8xMRETVnDDfWoF+VOHI0YIXBvvrxNlEhnpBKOZiYiIioKoYbSysvBc5t0z3meBsiIqJGx3BjaVd/B9R5gHsg0PJuq7wFVyYmIiKqncmzpar6z3/+g3//+99ISUlBaWmp0Wt//vmnRQprtvQL93UaCUgtnx2FEEhKZ8sNERFRbcz+9f3nP/+J6dOnIyAgAMeOHcPdd98NPz8/XL58GcOHDze7gBUrViAiIgJKpRLR0dHYs2dPnfur1WosWrQI4eHhUCgUaNu2LdauXWv2+1qFVlNxyQVYrUvqek4x8kvK4SyTon0g1xYiIiK6ndktNytWrMCqVavw6KOP4ssvv8TLL7+MNm3aYPHixcjJyTHrXAkJCZg3bx5WrFiBfv364fPPP8fw4cORlJSEVq1a1XjMhAkTcOPGDaxZswbt2rVDZmYmysvLzf0Y1nH9D6DwJqD0AloPsMpbnE7TdUl1DPKAXMZeRSIiotuZHW5SUlLQt29fAICLiwvy8/MBAJMnT8Y999yDTz75xORzLV++HDNnzjRckyo+Ph7bt2/HypUrERcXV23/bdu2Yffu3bh8+TJ8fX0BoGldrFPfJdVxBCCTW+UtzlSEmy5cmZiIiKhGZv/TPygoCNnZ2QCA8PBwHDx4EABw5coVCCFMPk9paSmOHj2K2NhYo+2xsbHYv39/jcf88MMPiImJwbvvvovQ0FB06NABCxYsQHFxca3vo1aroVKpjG5WIQSQXGUKuJWcTtXVH8XxNkRERDUyu+Xm/vvvx48//oiePXti5syZeOGFF/Cf//wHR44cwfjx400+T1ZWFjQaDQIDA422BwYGIiMjo8ZjLl++jL1790KpVOK///0vsrKy8PTTTyMnJ6fWcTdxcXFYunSp6R+wvtJPAHkpgNwVaHu/Vd5CCFHZcsOZUkRERDUyO9ysWrUKWq0WADBnzhz4+vpi7969GD16NObMmWN2Abdf0VoIUetVrrVaLSQSCTZu3AgvL13LxfLly/Hwww/j008/hYuLS7VjFi5ciPnz5xueq1QqhIWFmV3nHQVEAo99WxFwqtdhCZn5amQVlEIqAToFMdwQERHVxOxwI5VKIa0yxXnChAmYMGGC2W/s7+8PmUxWrZUmMzOzWmuOXnBwMEJDQw3BBgAiIyMhhMBff/2F9u3bVztGoVBAoVCYXZ/ZnBRAh9g779cA+labdgHucHGWWfW9iIiImqt6TbfZs2cPHn/8cfTp0wepqakAgK+++gp79+41+RzOzs6Ijo5GYmKi0fbExETDgOXb9evXD2lpaSgoKDBsO3/+PKRSKVq2bFmPT9K86MfbcH0bIiKi2pkdbjZv3oyhQ4fCxcUFx44dg1qtBgDk5+fjrbfeMutc8+fPx+rVq7F27VokJyfjhRdeQEpKiqF7a+HChZgyZYph/8ceewx+fn6YPn06kpKS8Pvvv+Oll17CjBkzauySsjf6lhuuTExERFQ7s8PNG2+8gc8++wxffPEF5PLK6c59+/Y1e3XiiRMnIj4+HsuWLUP37t3x+++/Y+vWrQgPDwcApKenIyUlxbC/u7s7EhMTkZubi5iYGEyaNAmjR4/GP//5T3M/RrPElhsiIqI7kwhz5m8DcHV1RVJSElq3bg0PDw+cOHECbdq0weXLlxEVFYWSkhJr1WoRKpUKXl5eyMvLg6dn82kByS0qRfdlui68E0ti4eVinXV0iIiImiJzfr/NbrkJDg7GxYsXq23fu3cv2rRpY+7pyET6K4G38nVlsCEiIqqD2eFm9uzZeP755/HHH39AIpEgLS0NGzduxIIFC/D0009bo0YCx9sQERGZyuyp4C+//DLy8vIwaNAglJSU4N5774VCocCCBQvw7LPPWqNGQuV4my6hHG9DRERUF7PCjUajwd69e/Hiiy9i0aJFSEpKglarRVRUFNzdeYVqa9K33ESx5YaIiKhOZoUbmUyGoUOHIjk5Gb6+voiJibFWXVRFobocl7MKAQBdOFOKiIioTmaPuenatSsuX75sjVqoFmczVBACCPBQoIVHI6y2TERE1IyZHW7efPNNLFiwAD/99BPS09Mb54rbDo7jbYiIiExn9oDiYcOGAQDGjBljdIFL/QUvNRqN5aojAJwpRUREZA6zw82uXbusUQfVgSsTExERmc7scDNw4MBaXzt+/HhDaqEaqMs1uJCZD4AtN0RERKao11XBq8rLy8OKFSvQs2dPREdHW6ImquLCjQKUaQS8XORo6WP/FwclIiJqqHqHm507d+Lxxx9HcHAwPv74Y4wYMQJHjhyxZG0E4/E2Vcc4ERERUc3M6pb666+/sH79eqxduxaFhYWYMGECysrKsHnzZkRFRVmrRofGmVJERETmMbnlZsSIEYiKikJSUhI+/vhjpKWl4eOPP7ZmbQTOlCIiIjKXyS03O3bswNy5c/HUU0+hffv21qyJKmi0Asnp+sHEbLkhIiIyhcktN3v27EF+fj5iYmLQu3dvfPLJJ7h586Y1a3N4V7IKUFymgYtchgh/N1uXQ0RE1CyYHG769OmDL774Aunp6Zg9eza++eYbhIaGQqvVIjExEfn5+das0yGdSdONt4kK8YRMysHEREREpjB7tpSrqytmzJiBvXv34tSpU3jxxRfx9ttvIyAgAGPGjLFGjQ7rdCrH2xAREZmrQevcdOzYEe+++y7++usvfP3115aqiSroW254JXAiIiLTNXgRPwCQyWQYN24cfvjhB0ucjqC7Vpe+5SaKLTdEREQms0i4Icv761YxVCXlkMsk6BDoYetyiIiImg2GmyZKv75Nh0APODvxayIiIjIVfzWbKI63ISIiqh+GmybKMFMqlONtiIiIzMFw00TpW244DZyIiMg8DDdNUGZ+CTLz1ZBIgMhghhsiIiJzMNw0QfpWmzb+bnB1NuvC7URERA6P4aYJOlMx3qZLKAcTExERmYvhpgnieBsiIqL6Y7hpgk5XrHHDaeBERETmY7hpYvKKynA9pxgAL7tARERUHww3TcyZdF2rTUsfF3i7Otu4GiIiouaH4aaJSeJ4GyIiogZhuGli9CsTc7wNERFR/TDcNDGGmVK87AIREVG9MNw0IcWlGly6WQCALTdERET1xXDThCRnqKAVgL+7AgGeSluXQ0RE1Cwx3DQhlSsTs0uKiIiovhhumhCuTExERNRwDDdNCFcmJiIiajiGmyaitFyL8xm6wcSdGW6IiIjqjeGmibiQmY9SjRYeSieE+brYuhwiIqJmi+Gmiag63kYikdi4GiIiouaL4aaJOMOViYmIiCyC4aaJ4MrERERElsFw0wRotQJJ6bpww5YbIiKihmG4aQKuZBeiqFQDpVyKNi3cbV0OERFRs8Zw0wTou6Q6BXlCJuVgYiIiooZguGkCeNkFIiIiy7F5uFmxYgUiIiKgVCoRHR2NPXv21Lrvb7/9BolEUu129uzZRqzY8iqngXO8DRERUUPZNNwkJCRg3rx5WLRoEY4dO4YBAwZg+PDhSElJqfO4c+fOIT093XBr3759I1VseUIIXnaBiIjIgmwabpYvX46ZM2di1qxZiIyMRHx8PMLCwrBy5co6jwsICEBQUJDhJpPJGqliy0vLK0FuURmcpBJ0COJgYiIiooayWbgpLS3F0aNHERsba7Q9NjYW+/fvr/PYHj16IDg4GIMHD8auXbvq3FetVkOlUhndmpLTFeNt2gd6QOHUfEMaERFRU2GzcJOVlQWNRoPAwECj7YGBgcjIyKjxmODgYKxatQqbN2/Gd999h44dO2Lw4MH4/fffa32fuLg4eHl5GW5hYWEW/RwNVfWyC0RERNRwTrYu4PbrKAkhar22UseOHdGxY0fD8z59+uD69et4//33ce+999Z4zMKFCzF//nzDc5VK1aQCTuVlFxhuiIiILMFmLTf+/v6QyWTVWmkyMzOrtebU5Z577sGFCxdqfV2hUMDT09Po1pRUXnaBg4mJiIgswWbhxtnZGdHR0UhMTDTanpiYiL59+5p8nmPHjiE4ONjS5TWKrAI1MlQlkEiAyOCmFbqIiIiaK5t2S82fPx+TJ09GTEwM+vTpg1WrViElJQVz5swBoOtSSk1NxYYNGwAA8fHxaN26NTp37ozS0lL861//wubNm7F582Zbfox607faRPi5wV1h8x5CIiIiu2DTX9SJEyciOzsby5YtQ3p6Orp06YKtW7ciPDwcAJCenm605k1paSkWLFiA1NRUuLi4oHPnztiyZQtGjBhhq4/QIPqZUuySIiIishyJEELYuojGpFKp4OXlhby8PJuPv3lm45/YciodrwzvhDkD29q0FiIioqbMnN9vm19+wZFxZWIiIiLLY7ixEVVJGa5lFwHgGjdERESWxHBjI0kVg4lDvV3g4+Zs42qIiIjsB8ONjehnSkWx1YaIiMiiGG5spHJlYo63ISIisiSGGxvhNaWIiIisg+HGBkrKNLh4swAA0IVr3BAREVkUw40NnM3Ih0Yr4OfmjEBPha3LISIisisMNzZQdWXi2q6ATkRERPXDcGMDHG9DRERkPQw3NnCGKxMTERFZDcNNIyvTaHE2Ix8AW26IiIisgeGmkV3MLEBpuRbuCie08nW1dTlERER2h+GmkVVdmVgq5WBiIiIiS2O4aWT68TbskiIiIrIOhptGdiZV13LDwcRERETWwXDTiLRagaT0imngoWy5ISIisgaGm0Z0LacIBepyKJykaNfC3dblEBER2SWGm0akH2/TKcgDTjL+6YmIiKyBv7CN6HSqvkuK422IiIisheGmEXGmFBERkfUx3DQSIYRhjRvOlCIiIrIehptGkqEqQU5hKWRSCToGedi6HCIiIrvFcNNI9ONt2ge4QymX2bgaIiIi+8Vw00j0422iON6GiIjIqhhuGslprkxMRETUKBhuGkkSZ0oRERE1CoabRpBTWIq0vBIA7JYiIiKyNoabRqAfb9PazxUeSrmNqyEiIrJvDDeNgCsTExERNR6Gm0bAlYmJiIgaD8NNI+DKxERERI2H4cbK8kvKcCWrEABbboiIiBoDw42VJafnAwCCvZTwc1fYuBoiIiL7x3BjZRxvQ0RE1LgYbqxMP1MqiuNtiIiIGgXDjZXpW266sOWGiIioUTDcWFFJmQYXMgsAcI0bIiKixsJwY0Xnb+RDoxXwcZUjxEtp63KIiIgcAsONFRlWJg7xgkQisXE1REREjoHhxooMM6VCOd6GiIiosTDcWJF+ZeLOnClFRETUaBhurKRco0Vyuv6yC2y5ISIiaiwMN1ZyOasQ6nIt3JxlaO3nZutyiIiIHAbDjZWcTtWNt4kK8YRUysHEREREjYXhxko43oaIiMg2GG6sRN9yw2tKERERNS6GGyvQagWS2HJDRERkEzYPNytWrEBERASUSiWio6OxZ88ek47bt28fnJyc0L17d+sWWA/XbxUhX10OZ5kU7QPdbV0OERGRQ7FpuElISMC8efOwaNEiHDt2DAMGDMDw4cORkpJS53F5eXmYMmUKBg8e3EiVmkc/3qZjkAfkMpvnRyIiIodi01/e5cuXY+bMmZg1axYiIyMRHx+PsLAwrFy5ss7jZs+ejcceewx9+vRppErNox9v04UrExMRETU6m4Wb0tJSHD16FLGxsUbbY2NjsX///lqPW7duHS5duoQlS5aY9D5qtRoqlcroZm36lpsojrchIiJqdDYLN1lZWdBoNAgMDDTaHhgYiIyMjBqPuXDhAl555RVs3LgRTk5OJr1PXFwcvLy8DLewsLAG114XIYThmlJcmZiIiKjx2XxAyO1XyxZC1HgFbY1Gg8ceewxLly5Fhw4dTD7/woULkZeXZ7hdv369wTXXJTNfjayCUkglQKcghhsiIqLGZlrzhxX4+/tDJpNVa6XJzMys1poDAPn5+Thy5AiOHTuGZ599FgCg1WohhICTkxN27NiB+++/v9pxCoUCCoXCOh+iBvrxNu0C3OHiLGu09yUiIiIdm7XcODs7Izo6GomJiUbbExMT0bdv32r7e3p64tSpUzh+/LjhNmfOHHTs2BHHjx9H7969G6v0OnFlYiIiItuyWcsNAMyfPx+TJ09GTEwM+vTpg1WrViElJQVz5swBoOtSSk1NxYYNGyCVStGlSxej4wMCAqBUKqtttyWuTExERGRbNg03EydORHZ2NpYtW4b09HR06dIFW7duRXh4OAAgPT39jmveNDVsuSEiIrItiRBC2LqIxqRSqeDl5YW8vDx4elq2deVWYSl6/EPXzXZiSSy8XOQWPT8REZGjMuf32+azpexJUrqu1aaVryuDDRERkY0w3FgQx9sQERHZHsONBenH23QJ5XgbIiIiW2G4saDTFSsTR7HlhoiIyGYYbiykUF2OK1mFAIAunClFRERkMzadCm5P0vOKEeChgBBAC4/GWxGZiIiIjDHcWEi7AA/88eoQqErKbF0KERGRQ2O3lIV5KjkFnIiIyJYYboiIiMiuMNwQERGRXWG4ISIiIrvCcENERER2heGGiIiI7ArDDREREdkVhhsiIiKyKww3REREZFcYboiIiMiuMNwQERGRXWG4ISIiIrvCcENERER2heGGiIiI7IqTrQtobEIIAIBKpbJxJURERGQq/e+2/ne8Lg4XbvLz8wEAYWFhNq6EiIiIzJWfnw8vL68695EIUyKQHdFqtUhLS4OHhwckEolFz61SqRAWFobr16/D09PToucm8/H7aFr4fTQ9/E6aFn4fdRNCID8/HyEhIZBK6x5V43AtN1KpFC1btrTqe3h6evI/zCaE30fTwu+j6eF30rTw+6jdnVps9DigmIiIiOwKww0RERHZFYYbC1IoFFiyZAkUCoWtSyHw+2hq+H00PfxOmhZ+H5bjcAOKiYiIyL6x5YaIiIjsCsMNERER2RWGGyIiIrIrDDdERERkVxhuLGTFihWIiIiAUqlEdHQ09uzZY+uSHFZcXBx69eoFDw8PBAQEYNy4cTh37pyty6IKcXFxkEgkmDdvnq1LcVipqal4/PHH4efnB1dXV3Tv3h1Hjx61dVkOqby8HK+99hoiIiLg4uKCNm3aYNmyZdBqtbYurVljuLGAhIQEzJs3D4sWLcKxY8cwYMAADB8+HCkpKbYuzSHt3r0bzzzzDA4ePIjExESUl5cjNjYWhYWFti7N4R0+fBirVq1Ct27dbF2Kw7p16xb69esHuVyOn3/+GUlJSfjggw/g7e1t69Ic0jvvvIPPPvsMn3zyCZKTk/Huu+/ivffew8cff2zr0po1TgW3gN69e6Nnz55YuXKlYVtkZCTGjRuHuLg4G1ZGAHDz5k0EBARg9+7duPfee21djsMqKChAz549sWLFCrzxxhvo3r074uPjbV2Ww3nllVewb98+ti43EaNGjUJgYCDWrFlj2PbQQw/B1dUVX331lQ0ra97YctNApaWlOHr0KGJjY422x8bGYv/+/TaqiqrKy8sDAPj6+tq4Esf2zDPPYOTIkRgyZIitS3FoP/zwA2JiYvB///d/CAgIQI8ePfDFF1/YuiyH1b9/f/z66684f/48AODEiRPYu3cvRowYYePKmjeHu3CmpWVlZUGj0SAwMNBoe2BgIDIyMmxUFekJITB//nz0798fXbp0sXU5Duubb77Bn3/+icOHD9u6FId3+fJlrFy5EvPnz8err76KQ4cOYe7cuVAoFJgyZYqty3M4f/vb35CXl4dOnTpBJpNBo9HgzTffxKOPPmrr0po1hhsLkUgkRs+FENW2UeN79tlncfLkSezdu9fWpTis69ev4/nnn8eOHTugVCptXY7D02q1iImJwVtvvQUA6NGjB86cOYOVK1cy3NhAQkIC/vWvf2HTpk3o3Lkzjh8/jnnz5iEkJARTp061dXnNFsNNA/n7+0Mmk1VrpcnMzKzWmkON67nnnsMPP/yA33//HS1btrR1OQ7r6NGjyMzMRHR0tGGbRqPB77//jk8++QRqtRoymcyGFTqW4OBgREVFGW2LjIzE5s2bbVSRY3vppZfwyiuv4JFHHgEAdO3aFdeuXUNcXBzDTQNwzE0DOTs7Izo6GomJiUbbExMT0bdvXxtV5diEEHj22Wfx3XffYefOnYiIiLB1SQ5t8ODBOHXqFI4fP264xcTEYNKkSTh+/DiDTSPr169ftaURzp8/j/DwcBtV5NiKiooglRr/FMtkMk4FbyC23FjA/PnzMXnyZMTExKBPnz5YtWoVUlJSMGfOHFuX5pCeeeYZbNq0Cf/73//g4eFhaFXz8vKCi4uLjatzPB4eHtXGO7m5ucHPz4/joGzghRdeQN++ffHWW29hwoQJOHToEFatWoVVq1bZujSHNHr0aLz55pto1aoVOnfujGPHjmH58uWYMWOGrUtr3gRZxKeffirCw8OFs7Oz6Nmzp9i9e7etS3JYAGq8rVu3ztalUYWBAweK559/3tZlOKwff/xRdOnSRSgUCtGpUyexatUqW5fksFQqlXj++edFq1athFKpFG3atBGLFi0SarXa1qU1a1znhoiIiOwKx9wQERGRXWG4ISIiIrvCcENERER2heGGiIiI7ArDDREREdkVhhsiIiKyKww3REREZFcYboiIoLv47ffff2/rMojIAhhuiMjmpk2bBolEUu02bNgwW5dGRM0Qry1FRE3CsGHDsG7dOqNtCoXCRtUQUXPGlhsiahIUCgWCgoKMbj4+PgB0XUYrV67E8OHD4eLigoiICHz77bdGx586dQr3338/XFxc4OfnhyeffBIFBQVG+6xduxadO3eGQqFAcHAwnn32WaPXs7Ky8OCDD8LV1RXt27fHDz/8YN0PTURWwXBDRM3C66+/joceeggnTpzA448/jkcffRTJyckAgKKiIgwbNgw+Pj44fPgwvv32W/zyyy9G4WXlypV45pln8OSTT+LUqVP44Ycf0K5dO6P3WLp0KSZMmICTJ09ixIgRmDRpEnJychr1cxKRBdj6yp1ERFOnThUymUy4ubkZ3ZYtWyaE0F3pfc6cOUbH9O7dWzz11FNCCCFWrVolfHx8REFBgeH1LVu2CKlUKjIyMoQQQoSEhIhFixbVWgMA8dprrxmeFxQUCIlEIn7++WeLfU4iahwcc0NETcKgQYOwcuVKo22+vr6Gx3369DF6rU+fPjh+/DgAIDk5GXfddRfc3NwMr/fr1w9arRbnzp2DRCJBWloaBg8eXGcN3bp1Mzx2c3ODh4cHMjMz6/uRiMhGGG6IqElwc3Or1k10JxKJBAAghDA8rmkfFxcXk84nl8urHavVas2qiYhsj2NuiKhZOHjwYLXnnTp1AgBERUXh+PHjKCwsNLy+b98+SKVSdOjQAR4eHmjdujV+/fXXRq2ZiGyDLTdE1CSo1WpkZGQYbXNycoK/vz8A4Ntvv0VMTAz69++PjRs34tChQ1izZg0AYNKkSViyZAmmTp2Kv//977h58yaee+45TJ48GYGBgQCAv//975gzZw4CAgIwfPhw5OfnY9++fXjuueca94MSkdUx3BBRk7Bt2zYEBwcbbevYsSPOnj0LQDeT6ZtvvsHTTz+NoKAgbNy4EVFRUQAAV1dXbN++Hc8//zx69eoFV1dXPPTQQ1i+fLnhXFOnTkVJSQk+/PBDLFiwAP7+/nj44Ycb7wMSUaORCCGErYsgIqqLRCLBf//7X4wbN87WpRBRM8AxN0RERGRXGG6IiIjIrnDMDRE1eew9JyJzsOWGiIiI7ArDDREREdkVhhsiIiKyKww3REREZFcYboiIiMiuMNwQERGRXWG4ISIiIrvCcENERER2heGGiIiI7Mr/A1PvBtxMcl8CAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Plot the Area Under Curve(AUC) of loss during training\n",
    "plt.plot(history[\"train_auc_1\"])\n",
    "plt.plot(history[\"val_auc_1\"])\n",
    "plt.title(\"Model Area Under Curve\")\n",
    "plt.ylabel(\"Area Under Curve\")\n",
    "plt.xlabel(\"Epoch\")\n",
    "plt.legend([\"Train\", \"Val\"], loc=\"upper left\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ExPloit Attack实现&测试"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "epochs_attack = 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:SL Train Params: {'self': <ExP_attack.labelleakage.ExPloitattack.attach_ExPloitattack_to_splitnn_sf.<locals>.ExPloitAttackSplitNNWrapper_sf object at 0x7f26d8345ee0>, 'x': VDataFrame(partitions={PYURuntime(client): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f36ac0bb430>), PYURuntime(server): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f36195fd580>)}, aligned=True), 'y': VDataFrame(partitions={PYURuntime(server): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f26d83cd100>)}, aligned=True), 'batch_size': 1024, 'epochs': 10, 'verbose': 1, 'callbacks': None, 'test_data': (VDataFrame(partitions={PYURuntime(client): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f36195f4d90>), PYURuntime(server): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f26d83d4f70>)}, aligned=True), VDataFrame(partitions={PYURuntime(server): Partition(data=<secretflow.device.device.pyu.PYUObject object at 0x7f26d83cd1c0>)}, aligned=True)), 'shuffle': False, 'sample_weight': None, 'dp_spent_step_freq': None, 'dataset_builder': None, 'audit_log_dir': None, 'audit_log_params': {}, 'random_seed': 47744, 'surrogate_builder': <function create_surrogate_model.<locals>.create_model at 0x7f26d83d9550>, 'args_dict': {'H_y': <tf.Tensor: shape=(), dtype=float64, numpy=0.012714681335936208>, 'y_pri': <tf.Tensor: shape=(1, 2), dtype=float32, numpy=array([[0.99827254, 0.00172749]], dtype=float32)>, 'batch_size': 1024}}\n",
      " 94%|█████████▍| 209/222 [00:01<00:00, 199.15it/s]"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model: \"sequential\"\n",
      "_________________________________________________________________\n",
      " Layer (type)                Output Shape              Param #   \n",
      "=================================================================\n",
      " dense (Dense)               (None, 64)                1344      \n",
      "                                                                 \n",
      " dense_1 (Dense)             (None, 1)                 65        \n",
      "                                                                 \n",
      "=================================================================\n",
      "Total params: 1,409\n",
      "Trainable params: 1,409\n",
      "Non-trainable params: 0\n",
      "_________________________________________________________________\n",
      "===================================================================================================\n",
      "Epoch 1/10, Loss: 0.0008, Accuracy: 0.9954, AUC: 0.9259\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n",
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:53:19,512 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29472104448; capacity: 3936380534784. Object creation will fail if spilling is required.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===================================================================================================\n",
      "Epoch 2/10, Loss: 0.0003, Accuracy: 0.9994, AUC: 0.9436\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:53:29,518 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29471936512; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n",
      "100%|██████████| 222/222 [00:19<00:00, 199.15it/s]WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===================================================================================================\n",
      "Epoch 3/10, Loss: 0.0003, Accuracy: 0.9994, AUC: 0.9437\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:53:39,525 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29471789056; capacity: 3936380534784. Object creation will fail if spilling is required.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===================================================================================================\n",
      "Epoch 4/10, Loss: 0.0003, Accuracy: 0.9994, AUC: 0.9424\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n",
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n",
      "WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===================================================================================================\n",
      "Epoch 5/10, Loss: 0.0002, Accuracy: 0.9994, AUC: 0.9424\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:53:49,531 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29471666176; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===================================================================================================\n",
      "Epoch 6/10, Loss: 0.0002, Accuracy: 0.9994, AUC: 0.9437\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:53:59,538 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29471559680; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===================================================================================================\n",
      "Epoch 7/10, Loss: 0.0002, Accuracy: 0.9994, AUC: 0.9437\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===================================================================================================\n",
      "Epoch 8/10, Loss: 0.0002, Accuracy: 0.9994, AUC: 0.9437\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n",
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:54:09,545 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29471469568; capacity: 3936380534784. Object creation will fail if spilling is required.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===================================================================================================\n",
      "Epoch 9/10, Loss: 0.0002, Accuracy: 0.9994, AUC: 0.9437\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n",
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n",
      "WARNING:absl:Found untraced functions such as _update_step_xla while saving (showing 1 of 1). These functions will not be directly callable after loading.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "===================================================================================================\n",
      "Epoch 10/10, Loss: 0.0002, Accuracy: 0.9994, AUC: 0.9449\n",
      "===================================================================================================\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Assets written to: ./model/model.pth/assets\n",
      "100%|██████████| 222/222 [01:07<00:00,  3.28it/s] "
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "====================================================\n",
      "Test Accuracy: 0.9994, AUC: 0.9245\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:54:19,551 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29471350784; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:54:29,560 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29471047680; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:54:39,567 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29470855168; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:54:49,575 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29470519296; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:54:59,582 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29470384128; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:55:09,590 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29470294016; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:55:19,597 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29469962240; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:55:29,604 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29469581312; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:55:39,611 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29469405184; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:55:49,618 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29469200384; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:55:59,624 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29469065216; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:56:09,631 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29468925952; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:56:19,637 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29468741632; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:56:29,644 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29468614656; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:56:39,650 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29468434432; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:56:49,657 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29467283456; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:56:59,663 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29467152384; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:57:09,669 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29467037696; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:57:19,676 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29466898432; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:57:29,684 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29466771456; capacity: 3936380534784. Object creation will fail if spilling is required.\n",
      "\u001b[2m\u001b[33m(raylet)\u001b[0m [2023-10-07 20:57:39,694 E 1077406 1077449] (raylet) file_system_monitor.cc:105: /tmp/ray/session_2023-10-07_20-50-37_505313_1077117 is over 95% full, available space: 29466619904; capacity: 3936380534784. Object creation will fail if spilling is required.\n"
     ]
    }
   ],
   "source": [
    "ExPloitattacksplitnn.exploit_attack(\n",
    "    train_data,\n",
    "    train_label,\n",
    "    test_data=(test_data, test_label),\n",
    "    epochs=epochs_attack,\n",
    "    batch_size=train_batch_size,\n",
    "    shuffle=False,\n",
    "    verbose=1,\n",
    "    surrogate_builder=surrogate_builder,\n",
    "    args_dict=args_dict,\n",
    ")\n",
    "# dp_spent_step_freq=dp_spent_step_freq,)"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "sf",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
